home *** CD-ROM | disk | FTP | other *** search
/ OctaMED Sound Studio 1 / OctaMED SoundStudio V1.iso / soundstudio v1 / programmers / proplayer.a < prev    next >
Text File  |  1996-06-18  |  105KB  |  3,858 lines

  1. ;============================================================================
  2. ;    proplayer.a
  3. ;    ~~~~~~~~~~~
  4. ; $VER: proplayer 7.0 (11.2.1996)
  5. ;
  6. ; The music player routine for MMD0/MMD1/MMD2 MED/OctaMED
  7. ; four-channel modules.
  8. ;
  9. ; Copyright © 1995-1996 Teijo Kinnunen and RBF Software.
  10. ;
  11. ; Written by Teijo Kinnunen.
  12. ; Technical comments/questions/bug reports can be sent to:
  13. ;    Teijo Kinnunen
  14. ;    Oksantie 19
  15. ;    FIN-86300  OULAINEN
  16. ;    FINLAND
  17. ;    email: Teijo.Kinnunen@oulu.fi
  18. ;
  19. ; See OctaMED docs for conditions about using these routines.
  20. ; Comments/questions about distribution and usage conditions
  21. ; should be directed to RBF Software. (Email: rbfsoft@cix.compulink.co.uk)
  22. ;
  23. ;============================================================================
  24.  
  25. ;****** Feature control ******
  26. ;
  27. MIDI        EQU 0    ;1 = include MIDI code
  28. AUDDEV        EQU 1    ;1 = allocate channels using audio.device
  29. SYNTH        EQU 1    ;1 = include synth-sound handler
  30. CHECK        EQU 1    ;1 = do range checkings (track, sample in mem etc.)
  31. RELVOL        EQU 1    ;1 = include relative volume handling code
  32. IFFMOCT        EQU 1    ;1 = play IFF multi-octave samples/ExtSamples correctly
  33. HOLD        EQU 1    ;1 = handle hold/decay
  34. PLAYMMD0    EQU 1    ;1 = play old MMD0 modules
  35. FASTMEMPLAY    EQU 1    ;1 = make FastMemPlay available
  36. AURA        EQU 0    ;1 = support the Aura sampler
  37. ;
  38. ; The less features you include, the faster and shorter the play-routine
  39. ; will be.
  40. ;
  41. ;****** Timing control ******
  42. ;
  43. VBLANK    EQU    0    ;1 = use VBlank interrupt (when absolutely necessary)
  44. CIAB    EQU    1    ;1 = use CIA timers (default)
  45. ;
  46. ; Please use CIAB whenever possible to avoid problems with variable
  47. ; VBlank speeds and to allow the use of command F01 - FF0 (set tempo)
  48. ; If both are set to 0, the timing is left for you (never set both to 1!!),
  49. ; then you just call _IntHandler for each timing pulse.
  50.  
  51. ;============================================================================
  52.  
  53. ; The MMD structure offsets
  54. mmd_id        EQU    0
  55. mmd_modlen    EQU    4
  56. mmd_songinfo    EQU    8
  57. ; these two for MMD2s only!
  58. mmd_psecnum    EQU    12
  59. mmd_pseq    EQU    14
  60. ;
  61. mmd_blockarr    EQU    16
  62. mmd_smplarr    EQU    24
  63. mmd_expdata    EQU    32
  64. mmd_pstate    EQU    40 ; <0 = play song, 0 = don't play, >0 = play block
  65. mmd_pblock    EQU    42
  66. mmd_pline    EQU    44
  67. mmd_pseqnum    EQU    46
  68. mmd_counter    EQU    50
  69. mmd_songsleft    EQU    51
  70.  
  71. ; Instrument data
  72. inst_repeat    EQU    0
  73. inst_replen    EQU    2
  74. inst_midich    EQU    4
  75. inst_midipreset    EQU    5
  76. inst_svol    EQU    6
  77. inst_strans    EQU    7
  78.  
  79. ; Audio hardware offsets
  80. ac_ptr    EQU    $00
  81. ac_len    EQU    $04
  82. ac_per    EQU    $06
  83. ac_vol    EQU    $08
  84.  
  85.         INCLUDE    "medtrkdata.i"
  86.  
  87. ; Trackdata sizes
  88. T415SZ        SET    trk_previnstra
  89.  
  90. ; Maximum number of tracks allowed. If you don't need this much tracks,
  91. ; you can decrease the number to save some space. (Be sure that the
  92. ; song really has no more than MAX_NUMTRACKS tracks. Minimum allowed
  93. ; value = 4.)
  94. MAX_NUMTRACKS    EQU    64
  95.  
  96. ; This value is used for MMD0/1 conversion. If MAX_NUMTRACKS <= 16,
  97. ; this should be the same. If MAX_NUMTRACKS > 16, this should be 16.
  98. MAX_MMD1_TRACKS    EQU    16
  99.  
  100. ; Aura output handling routines
  101.     IFNE    AURA
  102.         ;also includes the SECTION cmd...
  103.         INCLUDE    "aura.a"
  104.     ENDC
  105.     IFEQ    AURA
  106.         SECTION    "text",CODE
  107.     ENDC
  108.  
  109. ; -------- _ChannelOff: Turn off a channel -------------------------------
  110. _ChannelOff:    ;d0 = channel #
  111.         lea    DB,a0
  112.         lea    trackdataptrs-DB(a0),a1
  113.         lsl.w    #2,d0
  114.         adda.w    d0,a1
  115.         lsr.w    #2,d0
  116.         movea.l    (a1),a1
  117.         move.b    trk_outputdev(a1),d1
  118.     IFNE    AURA
  119.         beq.s    choff_outstd
  120.         subq.b    #1,d1
  121.         bne.s    notamigatrk    ;unknown type... do nothing
  122.         jmp    _StopAura(pc)    ;AURA off
  123. choff_outstd
  124.     ENDC
  125.     IFEQ    AURA
  126.         bne.s    notamigatrk
  127.     ENDC
  128.     IFNE    MIDI
  129.         move.b    trk_prevmidin(a1),d1    ;first: is it MIDI??
  130.         beq.s    notcomidi    ;not a midi note
  131. ; -------- TURN OFF MIDI TRACK -------------------------------------------
  132.         lea    noteondata-DB(a0),a0
  133. choff_midi:    clr.b    trk_prevmidin(a1)
  134.         move.b    d1,1(a0)
  135.         bmi.s    notamigatrk
  136.         move.b    trk_prevmidich(a1),(a0)    ;prev midi channel
  137.         clr.b    2(a0)
  138.         or.b    #$90,(a0)        ;note off
  139.         moveq    #3,d0
  140.         bra.w    _AddMIDIData
  141.     ENDC
  142. notcomidi:    cmp.b    #4,d0
  143.         bge.s    notamigatrk
  144. ; -------- TURN OFF AMIGA-CHANNEL ----------------------------------------
  145.     IFNE    FASTMEMPLAY
  146.         tst.w    _use_fastmem-DB(a0)
  147.         beq.s    1$
  148.         movea.l    trk_fmp(a1),a0
  149.         clr.b    fmp_active(a0)
  150. 1$
  151.     ENDC
  152.     IFNE    SYNTH
  153.         clr.l    trk_synthptr(a1)
  154.         clr.b    trk_synthtype(a1)
  155.     ENDC
  156.         clr.w    trk_soffset(a1)
  157.         moveq    #1,d1
  158.         lsl.w    d0,d1
  159.         move.w    d1,$dff096
  160. notamigatrk:    rts
  161.  
  162. ; -------- SoundOff: Turn off all channels -------------------------------
  163. SoundOff:    move.l    d2,-(sp)
  164.         moveq    #MAX_NUMTRACKS-1,d2
  165. SO_loop0    move.l    d2,d0
  166.         bsr.s    _ChannelOff
  167.         dbf    d2,SO_loop0
  168.         clr.l    _module        ;play nothing
  169.         move.l    (sp)+,d2
  170. SO_rts        rts
  171.  
  172. ; -------- _PlayNote: The note playing routine ---------------------------
  173. _PlayNote:    ;d7(w) = trk #, d1 = note #, d3(w) = instr # a3 = addr of instr
  174. ; -------- CHECK INSTRUMENT (existence, type) ----------------------------
  175.         move.l    a3,d4
  176.         beq.s    SO_rts
  177.         moveq    #0,d4
  178.         bset    d7,d4    ;d4 is mask for this channel
  179.         movea.l    mmd_smplarr(a2),a0
  180.         add.w    d3,d3            ;d3 = instr.num << 2
  181.         add.w    d3,d3
  182.         move.w    d3,d6
  183.         add.w    d6,d6            ;inst # * 8
  184.         move.l    0(a0,d3.w),d5        ;get address of instrument
  185.     IFNE    MIDI
  186.         bne.s    inmem
  187.         tst.b    inst_midich(a3)        ;is MIDI channel set?
  188.     ENDC
  189.     IFNE    CHECK
  190.         beq.w    pnote_rts        ; NO!!!
  191.     ENDC
  192. ; -------- ADD TRANSPOSE -------------------------------------------------
  193. inmem        add.b    msng_playtransp(a4),d1    ;add play transpose
  194.         add.b    inst_strans(a3),d1    ;and instr. transpose
  195.     IFNE    AURA
  196.         cmp.w    #3,d7
  197.         bne.s    pn_norelch3
  198.         tst.b    playing_aura-DB(a6)
  199.         bne.s    pn_offaura
  200. pn_norelch3
  201.     ENDC
  202.         move.b    trk_outputdev(a5),d3
  203.         beq.s    pn_offami
  204.     IFNE    AURA
  205.         subq.b    #1,d3
  206.         bne.s    noprevmidi
  207. pn_offaura    jsr    _StopAura(pc)
  208.     ENDC
  209.         bra.s    noprevmidi        ;dunno.. unsupported type
  210.     
  211. ; -------- TURN OFF CHANNEL DMA, IF REQUIRED -----------------------------
  212. pn_offami    cmp.b    #4,d7
  213.         bge.s    nodmaoff    ;track # >= 4: not an Amiga channel
  214.         move.l    d5,a1
  215.     IFNE    SYNTH
  216.         tst.l    d5
  217.         beq.s    stpdma
  218.         tst.b    trk_synthtype(a5)
  219.         ble.s    stpdma        ;prev. type = sample/hybrid
  220.         cmp.w    #-1,4(a1)    ;type == SYNTHETIC??
  221.         beq.s    nostpdma
  222.     ENDC
  223. stpdma:        move.w    d4,$dff096        ;stop this channel (dmacon)
  224.     IFNE    FASTMEMPLAY
  225.         move.l    trk_fmp(a5),d0
  226.         beq.s    nostpdma
  227.         move.l    d0,a0
  228.         st    fmp_synstart(a0)
  229.     ENDC
  230. nostpdma:
  231.     IFNE    SYNTH
  232.         clr.l    trk_synthptr(a5)
  233.     ENDC
  234. nodmaoff:    subq.b    #1,d1
  235.     IFNE    MIDI
  236. ; -------- KILL PREVIOUS MIDI NOTE ---------------------------------------
  237.         move.b    trk_prevmidin(a5),d3    ;get prev. midi note
  238.         beq.s    noprevmidi
  239.         clr.b    trk_prevmidin(a5)
  240.         lea    noteondata+2-DB(a6),a0
  241.         clr.b    (a0)
  242.         move.b    d3,-(a0)
  243.         bmi.s    noprevmidi
  244.         move.b    trk_prevmidich(a5),-(a0) ;prev midi channel
  245.         or.b    #$90,(a0)         ;note off
  246.         move.w    d1,-(sp)
  247.         moveq    #3,d0
  248.         bsr.w    _AddMIDId
  249.         move.w    (sp)+,d1
  250. noprevmidi
  251. ; -------- IF MIDI NOTE, CALL MIDI NOTE ROUTINE --------------------------
  252.         tst.b    inst_midich(a3)
  253.         bne.w    handleMIDInote
  254.     ENDC
  255. ; -------- TEST OUTPUT DEVICE AND BRANCH IF NOT STD ----------------------
  256.     IFEQ    MIDI
  257. noprevmidi
  258.     ENDC
  259.         tst.b    trk_outputdev(a5)
  260.         bne.w    handlenonstdout
  261. ; -------- SET SOME AMIGA-CHANNEL PARAMETERS -----------------------------
  262.     IFNE    CHECK
  263.         cmp.w    #4,d7        ;track > 3???
  264.         bge.w    pnote_rts    ;no Amiga instruments here!!!
  265.     ENDC
  266. ; handle decay (for tracks 0 - 3 only!!)
  267.     IFNE    HOLD
  268.         clr.b    trk_fadespd(a5)        ;no fade yet..
  269.         move.b    trk_initdecay(a5),trk_decay(a5)    ;set decay
  270.     ENDC
  271.         clr.w    trk_vibroffs(a5)    ;clr vibrato/tremolo offset
  272.         or.w    d4,dmaonmsk-DB(a6)
  273.         move.l    d5,a0
  274.     IFNE    SYNTH
  275. ; -------- IF SYNTH NOTE, CALL SYNTH ROUTINE -----------------------------
  276.         tst.w    4(a0)
  277.         bmi.w    handleSynthnote
  278.         clr.b    trk_synthtype(a5)
  279.     ENDC
  280. ; -------- CHECK NOTE RANGE ----------------------------------------------
  281. tlwtst0        tst.b    d1
  282.         bpl.s    notenot2low
  283.         add.b    #12,d1    ;note was too low, octave up
  284.         bra.s    tlwtst0
  285. notenot2low    cmp.b    #62,d1
  286.         ble.s    endpttest
  287.         sub.b    #12,d1    ;note was too high, octave down
  288. endpttest
  289.         moveq    #6,d4    ;skip (stereo+hdr) offset
  290.         lea    _periodtable+32-DB(a6),a1
  291.         move.b    trk_finetune(a5),d2    ;finetune value
  292.         add.b    d2,d2
  293.         add.b    d2,d2        ;multiply by 4...
  294.         ext.w    d2        ;extend
  295.         movea.l    0(a1,d2.w),a1    ;period table address
  296.         move.w    4(a0),d0    ;(Instr hdr in a0)
  297.         btst    #5,d0
  298.         beq.s    gid_nostereo
  299.         move.b    d7,d5
  300.         and.b    #3,d5
  301.         beq.s    gid_nostereo    ;ch 0/4 = play left (norm.)
  302.         cmp.b    #3,d5
  303.         beq.s    gid_nostereo    ;also for ch 3/7
  304.         add.l    (a0),d4        ;play right channel
  305. gid_nostereo
  306.     IFNE    IFFMOCT
  307.         and.w    #$F,d0
  308.         bne.s    gid_notnormal    ;note # in d1 (0 - ...)
  309.     ENDC
  310. gid_cont_ext    move.l    a1,trk_periodtbl(a5)
  311.         add.b    d1,d1
  312.         move.w    0(a1,d1.w),d5 ;put period to d5
  313.         move.l    a0,d0
  314.         move.l    (a0),d1        ;length
  315.         add.l    d4,d0        ;skip hdr and stereo
  316.         add.l    d0,d1        ;sample end pointer
  317.         lea    rptrptlen-DB(a6),a0
  318.         move.l    0(a0,d6.w),d2
  319.         move.l    4(a0,d6.w),d3
  320.     IFNE    IFFMOCT
  321.         bra    gid_setrept
  322. gid_addtable    dc.b    0,6,12,18,24,30
  323. gid_divtable    dc.b    31,7,3,15,63,127
  324. gid_notnormal    cmp.w    #7,d0
  325.         blt.s    gid_not_ext
  326.         suba.w    #48,a1
  327.         bra.s    gid_cont_ext
  328. gid_not_ext    move.l    d7,-(sp)
  329.         moveq    #0,d7
  330.         move.w    d1,d7
  331.         divu    #12,d7    ;octave #
  332.         move.l    d7,d5
  333.         cmp.w    #6,d7    ;if oct > 5, oct = 5
  334.         blt.s    nohioct
  335.         moveq    #5,d7
  336. nohioct        swap    d5    ;note number in this oct (0-11) is in d5
  337.         move.l    (a0),d1
  338.         cmp.w    #6,d0
  339.         ble.s    nounrecit
  340.         moveq    #6,d0
  341. nounrecit    add.b    gid_addtable-1(pc,d0.w),d7
  342.         move.b    gid_divtable-1(pc,d0.w),d0
  343.         divu    d0,d1    ;get length of the highest octave
  344.         swap    d1
  345.         clr.w    d1
  346.         swap    d1
  347.         move.l    d1,d0        ;d0 and d1 = length of the 1st oct
  348.         lea    rptrptlen-DB(a6),a3
  349.         move.l    0(a3,d6.w),d2
  350.         move.l    4(a3,d6.w),d3
  351.         moveq    #0,d6
  352.         move.b    shiftcnt(pc,d7.w),d6
  353.         lsl.l    d6,d2
  354.         lsl.l    d6,d3
  355.         lsl.l    d6,d1
  356.         move.b    mullencnt(pc,d7.w),d6
  357.         mulu    d6,d0        ;offset of this oct from 1st oct
  358.         add.l    a0,d0        ;add base address to offset
  359.         add.l    d4,d0        ;skip header + stereo
  360.         add.l    d0,d1
  361.         move.l    a1,trk_periodtbl(a5)
  362.         add.b    octstart(pc,d7.w),d5
  363.         add.b    d5,d5
  364.         move.w    0(a1,d5.w),d5
  365.         move.l    (sp)+,d7
  366.         bra.s    gid_setrept
  367. shiftcnt:    dc.b    4,3,2,1,1,0,2,2,1,1,0,0,1,1,0,0,0,0
  368.         dc.b    3,3,2,2,1,0,5,4,3,2,1,0,6,5,4,3,2,1
  369. mullencnt:    dc.b    15,7,3,1,1,0,3,3,1,1,0,0,1,1,0,0,0,0
  370.         dc.b    7,7,3,3,1,0,31,15,7,3,1,0,63,31,15,7,3,1
  371. octstart:    dc.b    12,12,12,12,24,24,0,12,12,24,24,36,0,12,12,24,36,36
  372.         dc.b    0,12,12,24,24,24,12,12,12,12,12,12,12,12,12,12,12,12
  373.     ENDC
  374. gid_setrept    add.l    d0,d2        ;rep. start pointer
  375.         moveq    #2,d4
  376.         cmp.l    d4,d3
  377.         bhi.s    gid_noreplen2
  378.         moveq    #0,d3        ;no repeat
  379.         bra.s    gid_cont
  380. gid_noreplen2    add.l    d2,d3        ;rep. end pointer
  381.  
  382. ; -------- CALCULATE START/END ADDRESSES ---------------------------------
  383. gid_cont    move.w    trk_soffset(a5),d4
  384.         add.l    d4,d0
  385.         cmp.l    d0,d1
  386.         bhi.s    pn_nooffsovf
  387.         sub.l    d4,d0
  388. pn_nooffsovf    tst.w    _use_fastmem-DB(a6)
  389.         bne.s    pn_fastmemplay
  390.         movea.l    trk_audioaddr(a5),a1 ;base of this channel's regs
  391.         move.l    d0,(a1)+        ;push ac_ptr
  392.         lea    flags-DB(a6),a0
  393.         moveq    #0,d4
  394.         move.b    trk_previnstr(a5),d4
  395.         btst    #0,0(a0,d4.w)        ;test flags.SSFLG_LOOP
  396.         bne.s    repeat
  397.         
  398.         move.l    #_chipzero,trk_sampleptr(a5) ;pointer of zero word
  399.         move.w    #1,trk_samplelen(a5)    ;length: 1 word
  400.         sub.l    d0,d1
  401.         lsr.l    #1,d1            ;shift length right
  402.         move.w    d1,(a1)+        ;and push to ac_len
  403.         bra.s    retsn1
  404.  
  405. repeat        move.l    d2,trk_sampleptr(a5)
  406.         move.l    d3,d1
  407.         sub.l    d0,d1
  408.         lsr.l    #1,d1
  409.         move.w    d1,(a1)+    ;ac_len
  410.         sub.l    d2,d3
  411.         lsr.l    #1,d3
  412.         move.w    d3,trk_samplelen(a5)
  413.                 
  414. retsn1        move.w    d5,trk_prevper(a5)
  415.     IFNE    SYNTH
  416.         tst.b    trk_synthtype(a5)
  417.         bne.w    hSn2
  418.     ENDC
  419. pnote_rts    rts
  420.  
  421.     IFNE    FASTMEMPLAY
  422. pn_fastmemplay    movea.l    trk_fmp(a5),a0
  423.         move.w    fmp_intmask(a0),d4
  424.         move.w    d4,INTENA    ;turn off this interrupt
  425.         or.w    d4,intonmsk-DB(a6)
  426.         st    fmp_active(a0)
  427.         lea    flags-DB(a6),a1
  428.         moveq    #0,d4
  429.         move.b    trk_previnstr(a5),d4
  430.         btst    #0,0(a1,d4.w)    ;LOOP on?
  431.         bne.s    pn_fmp_repeat
  432.         sub.l    d0,d1
  433.         moveq    #0,d2
  434.         movem.l    d0-d2,(a0)        ;fmp_currptr/len/rept
  435.         bra.s    retsn1
  436. pn_fmp_repeat    move.l    d3,d1
  437.         sub.l    d0,d1
  438.         sub.l    d2,d3
  439.         movem.l    d0-d3,(a0)        ;fmp_currptr/len/repeatptr/len
  440.         bra.s    retsn1
  441.     ENDC
  442.  
  443. handlenonstdout
  444.     IFNE    AURA
  445.         move.b    trk_outputdev(a5),d0
  446.         subq.b    #1,d0
  447.         bne.s    hnso_notaura
  448. ; -------- AURA NOTE PLAYER ROUTINE --------------------------------------
  449. ;    a0 = sample pointer, already set
  450.         moveq    #0,d0
  451.         move.w    trk_soffset(a5),d0
  452.         lea    _periodtable+32-DB(a6),a1
  453.         move.b    trk_finetune(a5),d2    ;finetune value
  454.         add.b    d2,d2
  455.         add.b    d2,d2
  456.         ext.w    d2
  457.         movea.l    0(a1,d2.w),a1        ;period table address
  458.         add.b    d1,d1
  459.         move.w    0(a1,d1.w),d1
  460.         moveq    #0,d2            ;end offset = 0
  461.         jsr    _PlayAura(pc)
  462. hnso_notaura
  463.     ENDC
  464.         rts
  465.  
  466.     IFNE    MIDI
  467. ; -------- MIDI NOTE PLAYER ROUTINE --------------------------------------
  468. handleMIDInote:
  469.     IFNE    PLAYMMD0
  470.         cmp.b    #'1',3(a2)
  471.         bge.s    plr_mmd1_3
  472.         add.b    #24,d1
  473. plr_mmd1_3
  474.     ENDC
  475. ; -------- CHECK & SCALE VOLUME ------------------------------------------
  476.         move.b    trk_prevvol(a5),d2 ;temporarily save the volume
  477.     IFNE    RELVOL
  478. ; -------- GetRelVol: Calculate track volume -----------------------------
  479.         ext.w    d2
  480.         mulu    trk_trackvol(a5),d2
  481.         lsr.w    #7,d2
  482.     ENDC
  483.     IFEQ    RELVOL
  484.         lsl.b    #1,d2
  485.     ENDC
  486.         subq.b    #1,d2        ;if 128 => 127
  487.         bpl.s    hmn_notvolu0
  488.         moveq    #0,d2
  489. hmn_notvolu0
  490.         moveq    #0,d5
  491. ; -------- CHECK MIDI CHANNEL --------------------------------------------
  492.         move.b    inst_midich(a3),d5 ;get midi chan of this instrument
  493.         bpl.s    hmn_nosmof    ;bit 7 clear
  494.         clr.b    trk_prevmidin(a5)    ;suppress note off!
  495.         bra.s    hmn_smof
  496. hmn_nosmof    move.b    d1,trk_prevmidin(a5)
  497. hmn_smof    and.b    #$1F,d5        ;clear all flag bits etc...
  498.         subq.b    #1,d5        ;from 1-16 to 0-15
  499.         move.b    d5,trk_prevmidich(a5)    ;save to prev midi channel
  500.  
  501. ; -------- CHECK MIDI PRESET ---------------------------------------------
  502.         moveq    #0,d0
  503.         move.b    trk_previnstr(a5),d0
  504.         add.w    d0,d0
  505.         lea    ext_midipsets-DB(a6),a1
  506.         move.w    0(a1,d0.w),d0    ;get preset #
  507.         beq.s    nochgpres    ;zero = no preset
  508.         lea    prevmidicpres-DB(a6),a1
  509.         adda.w    d5,a1
  510.         adda.w    d5,a1
  511.         cmp.w    (a1),d0        ;is this previous preset ??
  512.         beq.s    nochgpres    ;yes...no need to change
  513.         move.w    d0,(a1)        ;save preset to prevmidicpres
  514.         subq.w    #1,d0        ;sub 1 to get 0 - 127
  515.         btst    #6,inst_midich(a3)
  516.         bne.s    hmn_extpreset
  517. ; -------- PREPARE PRESET CHANGE COMMAND ---------------------------------
  518. hmn_ordpreset    lea    preschgdata+1-DB(a6),a0
  519.         move.b    d0,(a0)        ;push the number to second byte
  520.         moveq    #2,d0
  521. hmn_sendpreset    move.b    #$c0,-(a0)    ;command: $C
  522.         or.b    d5,(a0)        ;"or" midi channel
  523.         move.w    d1,-(sp)
  524.         bsr.w    _AddMIDId
  525.         move.w    (sp)+,d1
  526.         tst.b    d2
  527.         beq.s    hmn_suppress    ;vol = 0, don't send NOTE ON
  528.  
  529. ; -------- PREPARE & SEND NOTE ON COMMAND --------------------------------
  530. nochgpres    lea    bytesinnotebuff-DB(a6),a0
  531.         movea.l    a0,a1
  532.         adda.w    (a0)+,a0
  533.         or.b    #$90,d5        ;MIDI: Note on
  534.         move.b    d5,(a0)+    ;MIDI msg Note on & channel
  535.         move.b    d1,(a0)+    ;MIDI msg note #
  536.         move.b    d2,(a0)        ;MIDI msg volume
  537.         beq.s    hmn_suppress    ;vol = 0 -> no note
  538.         addq.w    #3,(a1)
  539.         rts
  540. hmn_suppress    st    trk_prevmidin(a5)
  541.         rts
  542.  
  543. ; -------- HANDLE EXTENDED PRESET ----------------------------------------
  544. hmn_extpreset    cmp.w    #100,d0
  545.         blt.s    hmn_ordpreset
  546.         moveq    #99,d3
  547. hmn_loop100    sub.w    #100,d0
  548.         addq.b    #1,d3
  549.         cmp.w    #100,d0
  550.         bge.s    hmn_loop100
  551.         lea    preschgdata+2-DB(a6),a0
  552.         move.b    d0,(a0)        ;push the <= 99 number
  553.         move.b    d3,-(a0)    ;push the >= 100 number
  554.         moveq    #3,d0
  555.         bra.s    hmn_sendpreset
  556.     ENDC
  557.  
  558.     IFNE    SYNTH
  559. ; -------- TRIGGER SYNTH NOTE, CLEAR PARAMETERS --------------------------
  560. handleSynthnote    move.b    d1,trk_prevnote2(a5)
  561.         move.l    a0,trk_synthptr(a5)
  562.         cmp.w    #-2,4(a0)    ;HYBRID??
  563.         bne.s    hSn_nossn
  564.         st    trk_synthtype(a5)
  565.         movea.l    278(a0),a0    ;yep, get the waveform pointer
  566.         bra.w    tlwtst0        ;go and play it
  567. hSn_nossn:    move.b    #1,trk_synthtype(a5)
  568.         lea    _periodtable+32-DB(a6),a1
  569.         move.b    trk_finetune(a5),d0    ;finetune value
  570.         add.b    d0,d0
  571.         add.b    d0,d0        ;multiple by 4...
  572.         ext.w    d0        ;extend
  573.         movea.l    0(a1,d0.w),a1    ;period table address
  574.         suba.w    #48,a1
  575.         move.l    a1,trk_periodtbl(a5) ;save table ptr for synth periods
  576.         add.w    d1,d1
  577.         move.w    0(a1,d1.w),d1
  578.         move.w    d1,trk_prevper(a5)
  579.         clr.l    trk_sampleptr(a5)
  580. hSn2:        lea    trk_arpgoffs(a5),a1
  581.         clr.l    (a1)+
  582.         clr.l    (a1)+
  583.         btst    #0,trk_miscflags(a5)
  584.         bne.s    hSn_cmdE ;cmd E given, don't clear trk_wfcmd!
  585.         clr.w    (a1)
  586. hSn_cmdE    addq.l    #2,a1
  587.         clr.w    (a1)+
  588.         clr.l    (a1)+
  589.         clr.l    (a1)+
  590.         clr.l    (a1)+
  591.         move.l    #sinetable,(a1)+
  592.         clr.w    (a1)+
  593.         movea.l    trk_synthptr(a5),a0
  594.                 move.w    18(a0),(a1)+
  595.                 clr.b    (a1)
  596.         moveq    #64,d4
  597.         rts
  598.  
  599. synth_start    move.w    trk_prevper(a5),d5
  600. synth_start2    move.l    a3,-(sp)    ;d0 = SynthPtr
  601.         move.l    d0,a0
  602.         movea.l    trk_audioaddr(a5),a3    ;audio channel base address
  603. ; -------- SYNTHSOUND VOLUME SEQUENCE HANDLING ---------------------------
  604.         subq.b    #1,trk_volxcnt(a5)    ;decrease execute counter..
  605.         bgt.w    synth_wftbl        ;not 0...go to waveform
  606.         move.b    trk_initvolxspd(a5),trk_volxcnt(a5) ;reset counter
  607.         move.b    trk_volchgspd(a5),d0    ;volume change??
  608.         beq.s    synth_nochgvol        ;no.
  609.         add.b    trk_synvol(a5),d0    ;add previous volume
  610.         bpl.s    synth_voln2l        ;not negative
  611.         moveq    #0,d0            ;was negative => 0
  612. synth_voln2l    cmp.b    #$40,d0            ;too high??
  613.         ble.s    synth_voln2h        ;not 2 high.
  614.         moveq    #$40,d0            ;was 2 high => 64
  615. synth_voln2h    move.b    d0,trk_synvol(a5)    ;remember new...
  616. synth_nochgvol    move.l    trk_envptr(a5),d1    ;envelope pointer
  617.         beq.s    synth_novolenv
  618.         movea.l    d1,a1
  619.         move.b    (a1)+,d0
  620.         add.b    #128,d0
  621.         lsr.b    #2,d0
  622.         move.b    d0,trk_synvol(a5)
  623.         addq.b    #1,trk_envcount(a5)
  624.         bpl.s    synth_endenv
  625.         clr.b    trk_envcount(a5)
  626.         move.l    trk_envrestart(a5),a1
  627. synth_endenv    move.l    a1,trk_envptr(a5)
  628. synth_novolenv    move.w    trk_volcmd(a5),d0    ;get table position ptr
  629.         tst.b    trk_volwait(a5)        ;WAI(t) active
  630.         beq.s    synth_getvolcmd        ;no
  631.         subq.b    #1,trk_volwait(a5)    ;yep, decr wait ctr
  632.         ble.s    synth_getvolcmd        ;0 => continue
  633.         bra.w    synth_wftbl        ;> 0 => still wait
  634. synth_inccnt    addq.b    #1,d0
  635. synth_getvolcmd    addq.b    #1,d0            ;advance pointer
  636.         move.b    21(a0,d0.w),d1        ;get command
  637.         bmi.s    synth_cmd        ;negative = command
  638.         move.b    d1,trk_synvol(a5)    ;set synthvol
  639.         bra.w    synth_endvol        ;end of volume executing
  640. synth_cmd    and.w    #$000f,d1
  641.         add.b    d1,d1
  642.         move.w    synth_vtbl(pc,d1.w),d1
  643.         jmp    syv(pc,d1.w)
  644. synth_vtbl    dc.w    syv_f0-syv,syv_f1-syv,syv_f2-syv,syv_f3-syv
  645.         dc.w    syv_f4-syv,syv_f5-syv,syv_f6-syv
  646.         dc.w    synth_endvol-syv,synth_endvol-syv,synth_endvol-syv
  647.         dc.w    syv_fa-syv,syv_ff-syv,synth_endvol-syv
  648.         dc.w    synth_endvol-syv,syv_fe-syv,syv_ff-syv
  649. ; -------- VOLUME SEQUENCE COMMANDS --------------------------------------
  650. syv
  651. syv_fe        move.b    22(a0,d0.w),d0        ;JMP
  652.         bra.s    synth_getvolcmd
  653. syv_f0        move.b    22(a0,d0.w),trk_initvolxspd(a5) ;change volume ex. speed
  654.         bra.s    synth_inccnt
  655. syv_f1        move.b    22(a0,d0.w),trk_volwait(a5)    ;WAI(t)
  656.         addq.b    #1,d0
  657.         bra.s    synth_endvol
  658. syv_f3        move.b    22(a0,d0.w),trk_volchgspd(a5) ;set volume slide up
  659.         bra.s    synth_inccnt
  660. syv_f2        move.b    22(a0,d0.w),d1
  661.         neg.b    d1
  662.         move.b    d1,trk_volchgspd(a5) ;set volume slide down
  663.         bra.s    synth_inccnt
  664. syv_fa        move.b    22(a0,d0.w),trk_wfcmd+1(a5) ;JWS (jump wform sequence)
  665.         clr.b    trk_wfwait(a5)
  666.         bra.s    synth_inccnt
  667. syv_f4        move.b    22(a0,d0.w),d1
  668.         bsr.s    synth_getwf
  669.         clr.l    trk_envrestart(a5)
  670. syv_f4end    move.l    a1,trk_envptr(a5)
  671.         clr.b    trk_envcount(a5)
  672.         bra.w    synth_inccnt
  673. syv_f5        move.b    22(a0,d0.w),d1
  674.         bsr.s    synth_getwf
  675.         move.l    a1,trk_envrestart(a5)
  676.         bra.s    syv_f4end
  677. syv_f6        clr.l    trk_envptr(a5)
  678.         bra.w    synth_getvolcmd
  679. synth_getwf    ext.w    d1    ;d1 = wform number, returns ptr in a1
  680.         add.w    d1,d1    ;create index
  681.         add.w    d1,d1
  682.         lea    278(a0),a1
  683.         adda.w    d1,a1
  684.         movea.l    (a1),a1        ;get wform address
  685.         addq.l    #2,a1        ;skip length
  686.         rts
  687. syv_ff        subq.b    #1,d0
  688. synth_endvol    move.w    d0,trk_volcmd(a5)
  689. synth_wftbl    moveq    #0,d0
  690.         move.b    trk_synvol(a5),d0
  691.         moveq    #0,d1
  692.         move.b    trk_prevvol(a5),d1
  693.         mulu    d0,d1
  694.         asr.w    #6,d1
  695.         move.b    d1,trk_tempvol(a5)
  696.         adda.w    #158,a0
  697. ; -------- SYNTHSOUND WAVEFORM SEQUENCE HANDLING -------------------------
  698.         subq.b    #1,trk_wfxcnt(a5)    ;decr. wf speed counter
  699.         bgt.w    synth_arpeggio        ;not yet...
  700.         move.b    trk_initwfxspd(a5),trk_wfxcnt(a5) ;restore speed counter
  701.         move.w    trk_wfcmd(a5),d0    ;get table pos offset
  702.         move.w    trk_wfchgspd(a5),d1    ;CHU/CHD ??
  703.         beq.s    synth_tstwfwai        ;0 = no change
  704.         add.w    trk_perchg(a5),d1    ;add value to current change
  705.         move.w    d1,trk_perchg(a5)    ;remember amount of change
  706. synth_tstwfwai    tst.b    trk_wfwait(a5)        ;WAI ??
  707.         beq.s    synth_getwfcmd        ;not waiting...
  708.         subq.b    #1,trk_wfwait(a5)    ;decr wait counter
  709.         beq.s    synth_getwfcmd        ;waiting finished
  710.         bra.w    synth_arpeggio        ;still sleep...
  711. synth_incwfc    addq.b    #1,d0
  712. synth_getwfcmd    addq.b    #1,d0            ;advance position counter
  713.         move.b    -9(a0,d0.w),d1        ;get command
  714.         bmi.s    synth_wfcmd        ;negative = command
  715.         ext.w    d1
  716.         add.w    d1,d1
  717.         add.w    d1,d1
  718.         movea.l    120(a0,d1.w),a1
  719.         move.l    a3,-(sp)
  720.     IFNE    FASTMEMPLAY
  721.         tst.w    _use_fastmem-DB(a6)
  722.         bne.w    synth_setfmpwf
  723.     ENDC
  724.         move.w    (a1)+,ac_len(a3)    ;push waveform length
  725.         move.l    a1,ac_ptr(a3)        ;and the new pointer
  726.         move.l    (sp)+,a3
  727.         bra.w    synth_wfend        ;no new commands now...
  728. synth_wfcmd    and.w    #$000f,d1        ;get the right nibble
  729.         add.b    d1,d1            ;* 2
  730.         move.w    synth_wfctbl(pc,d1.w),d1
  731.         jmp    syw(pc,d1.w)        ;jump to command
  732. synth_wfctbl    dc.w    syw_f0-syw,syw_f1-syw,syw_f2-syw,syw_f3-syw,syw_f4-syw
  733.         dc.w    syw_f5-syw,syw_f6-syw,syw_f7-syw,synth_wfend-syw
  734.         dc.w    synth_wfend-syw,syw_fa-syw,syw_ff-syw
  735.         dc.w    syw_fc-syw,synth_getwfcmd-syw,syw_fe-syw,syw_ff-syw
  736. ; -------- WAVEFORM SEQUENCE COMMANDS ------------------------------------
  737. syw
  738. syw_f7        move.b    -8(a0,d0.w),d1
  739.         ext.w    d1
  740.         add.w    d1,d1
  741.         add.w    d1,d1
  742.         movea.l    120(a0,d1.w),a1
  743.         addq.l    #2,a1
  744.         move.l    a1,trk_synvibwf(a5)
  745.         bra.s    synth_incwfc
  746. syw_fe        move.b    -8(a0,d0.w),d0        ;jump (JMP)
  747.         bra.s    synth_getwfcmd
  748. syw_fc        move.w    d0,trk_arpsoffs(a5)    ;new arpeggio begin
  749.         move.w    d0,trk_arpgoffs(a5)
  750. synth_findare    addq.b    #1,d0
  751.         tst.b    -9(a0,d0.w)
  752.         bpl.s    synth_findare
  753.         bra.w    synth_getwfcmd
  754. syw_f0        move.b    -8(a0,d0.w),trk_initwfxspd(a5)    ;new waveform speed
  755.         bra    synth_incwfc
  756. syw_f1        move.b    -8(a0,d0.w),trk_wfwait(a5)    ;wait waveform
  757.         addq.b    #1,d0
  758.         bra.s    synth_wfend
  759. syw_f4        move.b    -8(a0,d0.w),trk_synvibdep+1(a5)    ;set vibrato depth
  760.         bra.w    synth_incwfc
  761. syw_f5        move.b    -8(a0,d0.w),trk_synthvibspd+1(a5) ;set vibrato speed
  762.         addq.b    #1,trk_synthvibspd+1(a5)
  763.         bra.w    synth_incwfc
  764. syw_f2        moveq    #0,d1            ;set slide down
  765.         move.b    -8(a0,d0.w),d1
  766. synth_setsld    move.w    d1,trk_wfchgspd(a5)
  767.         bra.w    synth_incwfc
  768. syw_f3        move.b    -8(a0,d0.w),d1        ;set slide up
  769.         neg.b    d1
  770.         ext.w    d1
  771.         bra.s    synth_setsld
  772. syw_f6        clr.w    trk_perchg(a5)        ;reset period
  773.         move.w    trk_prevper(a5),d5
  774.         bra.w    synth_getwfcmd
  775. syw_fa        move.b    -8(a0,d0.w),trk_volcmd+1(a5) ;JVS (jump volume sequence)
  776.         clr.b    trk_volwait(a5)
  777.         bra.w    synth_incwfc
  778. syw_ff        subq.b    #1,d0        ;pointer = END - 1
  779. synth_wfend    move.w    d0,trk_wfcmd(a5)
  780. ; -------- HANDLE SYNTHSOUND ARPEGGIO ------------------------------------
  781. synth_arpeggio    move.w    trk_arpgoffs(a5),d0
  782.         beq.s    synth_vibrato
  783.         moveq    #0,d1
  784.         move.b    -8(a0,d0.w),d1
  785.         add.b    trk_prevnote2(a5),d1
  786.         movea.l    trk_periodtbl(a5),a1    ;get period table
  787.         add.w    d1,d1
  788.         move.w    0(a1,d1.w),d5
  789.         addq.b    #1,d0
  790.         tst.b    -8(a0,d0.w)
  791.         bpl.s    synth_noarpres
  792.         move.w    trk_arpsoffs(a5),d0
  793. synth_noarpres    move.w    d0,trk_arpgoffs(a5)
  794. ; -------- HANDLE SYNTHSOUND VIBRATO -------------------------------------
  795. synth_vibrato    move.w    trk_synvibdep(a5),d1    ;get vibrato depth
  796.         beq.s    synth_rts        ;0 => no vibrato
  797.         move.w    trk_synviboffs(a5),d0    ;get offset
  798.         lsr.w    #4,d0            ;/ 16
  799.         and.w    #$1f,d0            ;sinetable offset (0-31)
  800.         movea.l trk_synvibwf(a5),a0
  801.         move.b    0(a0,d0.w),d0       ;get a byte
  802.         ext.w    d0            ;to word
  803.         muls    d1,d0            ;amplify (* depth)
  804.         asr.w    #8,d0            ;and divide by 64
  805.         add.w    d0,d5            ;add vibrato...
  806.         move.w    trk_synthvibspd(a5),d0    ;vibrato speed
  807.         add.w    d0,trk_synviboffs(a5)    ;add to offset
  808. synth_rts    add.w    trk_perchg(a5),d5
  809.         cmp.w    #113,d5            ;overflow??
  810.         bge.s    synth_pern2h
  811.         moveq    #113,d1
  812. synth_pern2h    move.l    (sp)+,a3
  813.         rts
  814.     ENDC
  815. sinetable    dc.b    0,25,49,71,90,106,117,125,127,125,117,106,90,71,49
  816.         dc.b    25,0,-25,-49,-71,-90,-106,-117,-125,-127,-125,-117
  817.         dc.b    -106,-90,-71,-49,-25,0
  818.  
  819.         EVEN
  820.     IFNE    FASTMEMPLAY
  821. synth_setfmpwf    movea.l    trk_fmp(a5),a3
  822.         moveq    #0,d1
  823.         move.w    (a1)+,d1
  824.         add.l    d1,d1
  825.         exg    d1,a1
  826.         movem.l    d1/a1,fmp_repeatptr(a3)    ;an atomic operation
  827.         tst.b    fmp_synstart(a3)
  828.         beq.s    1$
  829.         movem.l    d1/a1,(a3)    ;set also currptr/len
  830.         clr.b    fmp_synstart(a3)
  831.         st    fmp_active(a3)
  832.         move.w    fmp_intmask(a3),d1
  833.         move.w    d1,INTENA
  834.         or.w    d1,intonmsk-DB(a6)
  835. 1$        move.l    (sp)+,a3
  836.         bra.w    synth_wfend
  837.     ENDC
  838.  
  839. _IntHandler:    movem.l    d2-d7/a2-a6,-(sp)
  840.     IFNE    CIAB|VBLANK
  841.         movea.l    a1,a6    ;get data base address (int_Data)
  842.     ENDC
  843.     IFEQ    CIAB|VBLANK
  844.         lea    DB,a6    ;don't expect a1 to contain DB address
  845.     ENDC
  846.         tst.b    bpmcounter-DB(a6)
  847.         bmi.s    plr_nobpm
  848.         subq.b    #1,bpmcounter-DB(a6)
  849.         ble.s    plr_bpmcnt0
  850.         bra.w    plr_exit
  851. plr_bpmcnt0    move.b    #4,bpmcounter-DB(a6)
  852. plr_nobpm    movea.l    _module-DB(a6),a2
  853.         move.l    a2,d0
  854.         beq.w    plr_exit
  855.     IFNE    MIDI
  856.         clr.b    lastcmdbyte-DB(a6)    ;no MIDI optimization
  857.     ENDC
  858.         tst.w    mmd_pstate(a2)
  859.         beq.w    plr_exit
  860.     IFNE    MIDI
  861.         clr.l    dmaonmsk-DB(a6)
  862.     ENDC
  863.     IFEQ    MIDI
  864.         clr.w    dmaonmsk-DB(a6)
  865.     ENDC
  866.         clr.w    intonmsk-DB(a6)
  867.         movea.l    mmd_songinfo(a2),a4
  868.         moveq    #0,d3
  869.         move.b    mmd_counter(a2),d3
  870.         addq.b    #1,d3
  871.         cmp.b    msng_tempo2(a4),d3
  872.         bge.s    plr_pnewnote    ;play new note
  873.         move.b    d3,mmd_counter(a2)
  874.         bne.w    nonewnote    ;do just fx
  875. ; --- new note!!
  876. plr_pnewnote:    clr.b    mmd_counter(a2)
  877.         tst.w    blkdelay-DB(a6)
  878.         beq.s    plr_noblkdelay
  879.         subq.w    #1,blkdelay-DB(a6)
  880.         bne.w    nonewnote
  881. ; --- now start to play it
  882. ; -------- GET ADDRESS OF NOTE DATA --------------------------------------
  883. plr_noblkdelay    move.w    mmd_pblock(a2),d0
  884.         bsr.w    GetNoteDataAddr
  885.         moveq    #0,d7        ;number of track
  886.         moveq    #0,d4
  887.     IFNE    PLAYMMD0
  888.         cmp.b    #'1',3(a2)
  889.         sge    d5        ;d5 set -> >= MMD1
  890.     ENDC
  891.         lea    trackdataptrs-DB(a6),a1
  892. ; -------- TRACK LOOP (FOR EACH TRACK) -----------------------------------
  893. plr_loop0:    movea.l    (a1)+,a5    ;get address of this track's struct
  894. ; ---------------- get the note numbers
  895.         moveq    #0,d3
  896.     IFNE    PLAYMMD0
  897.         tst.b    d5
  898.         bne.s    plr_mmd1_1
  899.         move.b    (a3)+,d0
  900.         move.b    (a3),d3
  901.         addq.l    #2,a3
  902.         lsr.b    #4,d3
  903.         bclr    #7,d0
  904.         beq.s    plr_bseti4
  905.         bset    #4,d3
  906. plr_bseti4    bclr    #6,d0
  907.         beq.s    plr_bseti5
  908.         bset    #5,d3
  909. plr_bseti5    move.b    d0,trk_currnote(a5)
  910.         beq.s    plr_nngok
  911.         move.b    d0,(a5)
  912.         bra.s    plr_nngok
  913. plr_mmd1_1
  914.     ENDC
  915.         move.b    (a3)+,d0    ;get the number of this note
  916.         bpl.s    plr_nothinote
  917.         moveq    #0,d0
  918. plr_nothinote    move.b    d0,trk_currnote(a5)
  919.         beq.s    plr_nosetprevn
  920.         move.b    d0,(a5)
  921. plr_nosetprevn    move.b    (a3),d3        ;instrument number
  922.         addq.l    #3,a3        ;adv. to next track
  923. ; ---------------- check if there's an instrument number
  924. plr_nngok    clr.b    trk_fxtype(a5)
  925.         and.w    #$3F,d3
  926.         beq.s    noinstnum
  927. ; ---------------- finally, save the number
  928.         subq.b    #1,d3
  929.         move.b    d3,trk_previnstr(a5) ;remember instr. number!
  930. ; ---------------- get the pointer of data's of this sample in Song-struct
  931.         move.w    d3,d0
  932.         asl.w    #3,d3
  933.         lea    0(a4,d3.w),a0    ;a0 contains now address of it
  934.         move.l    a0,trk_previnstra(a5)
  935. ; ---------------- get volume
  936.         move.b    inst_svol(a0),trk_prevvol(a5) ;vol of this instr
  937.         move.b    inst_strans(a0),trk_stransp(a5)
  938. ; ---------------- remember some values of this instrument
  939.         lea    holdvals-DB(a6),a0
  940.         adda.w    d0,a0
  941.     IFNE    HOLD
  942.         move.b    (a0),trk_inithold(a5)        ;hold
  943.         move.b    63(a0),trk_initdecay(a5)    ;decay
  944.     ENDC
  945.         move.b    2*63(a0),trk_finetune(a5)    ;finetune
  946.         move.b    6*63(a0),trk_outputdev(a5)    ;output dev
  947. ; ---------------- remember transpose
  948.         clr.w    trk_soffset(a5)        ;sample offset
  949.         clr.b    trk_miscflags(a5)    ;misc.
  950. noinstnum    addq.w    #1,d7
  951.         cmp.w    numtracks-DB(a6),d7
  952.         blt    plr_loop0
  953.         bsr.w    DoPreFXLoop
  954. ; -------- NOTE PLAYING LOOP ---------------------------------------------
  955.         moveq    #0,d7
  956.         lea    trackdataptrs-DB(a6),a1
  957. plr_loop2    movea.l    (a1)+,a5
  958.         tst.b    trk_fxtype(a5)
  959.         bne.s    plr_loop2_end
  960.         move.b    trk_currnote(a5),d1
  961.         beq.s    plr_loop2_end
  962. ; ---------------- play
  963.         move.l    a1,-(sp)
  964.         ext.w    d1
  965.         moveq    #0,d3
  966.         move.b    trk_previnstr(a5),d3    ;instr #
  967.         movea.l    trk_previnstra(a5),a3    ;instr data address
  968.         move.b    trk_inithold(a5),trk_noteoffcnt(a5) ;initialize hold
  969.         bne.s    plr_nohold0        ;not 0 -> OK
  970.         st    trk_noteoffcnt(a5)    ;0 -> hold = 0xff (-1)
  971. ; ---------------- and finally:
  972. plr_nohold0    bsr    _PlayNote        ;play it
  973.         move.l    (sp)+,a1
  974. plr_loop2_end    addq.w    #1,d7
  975.         cmp.w    numtracks-DB(a6),d7
  976.         blt.s    plr_loop2
  977. ; -------- THE REST... ---------------------------------------------------
  978.         bsr.s    AdvSngPtr
  979. nonewnote    bsr.w    DoFX
  980. plr_endfx:    bsr    _StartDMA    ;turn on DMA
  981. plr_exit:    movem.l    (sp)+,d2-d7/a2-a6
  982.     IFNE    VBLANK
  983.         moveq    #0,d0
  984.     ENDC
  985.         rts
  986.  
  987. ; and advance song pointers
  988. AdvSngPtr    move.l    mmd_pblock(a2),fxplineblk-DB(a6) ;store pline/block for fx
  989.         move.w    nextblockline-DB(a6),d1
  990.         beq.s    plr_advlinenum
  991.         clr.w    nextblockline-DB(a6)
  992.         subq.w    #1,d1
  993.         bra.s    plr_linenumset
  994. plr_advlinenum    move.w    mmd_pline(a2),d1    ;get current line #
  995.         addq.w    #1,d1            ;advance line number
  996. plr_linenumset    cmp.w    numlines-DB(a6),d1     ;advance block?
  997.         bhi.s    plr_chgblock        ;yes.
  998.         tst.b    nextblock-DB(a6)    ;command F00/1Dxx?
  999.         beq.w    plr_nochgblock        ;no, don't change block
  1000. ; -------- CHANGE BLOCK? -------------------------------------------------
  1001. plr_chgblock    tst.b    nxtnoclrln-DB(a6)
  1002.         bne.s    plr_noclrln
  1003.         moveq    #0,d1            ;clear line number
  1004. plr_noclrln    tst.w    mmd_pstate(a2)        ;play block or play song
  1005.         bpl.w    plr_nonewseq        ;play block only...
  1006.         cmp.b    #'2',3(a2)        ;MMD2?
  1007.         bcs.s    plr_noMMD2_0
  1008. ; ********* BELOW CODE FOR MMD2 ONLY ************************************
  1009. ; -------- CHANGE SEQUENCE -----------------------------------------------
  1010. plr_skipseq    move.w    mmd_pseq(a2),d0        ;actually stored as << 2
  1011.         movea.l    msng_pseqs(a4),a1    ;ptr to playseqs
  1012.         movea.l    0(a1,d0.w),a0        ;a0 = ptr to curr PlaySeq
  1013.         move.w    mmd_pseqnum(a2),d0    ;get play sequence number
  1014.         tst.b    nextblock-DB(a6)
  1015.         bmi.s    plr_noadvseq        ;Bxx sets nextblock to -1
  1016.         addq.w    #1,d0            ;advance sequence number
  1017. plr_noadvseq    cmp.w    40(a0),d0        ;is this the highest seq number??
  1018.         blt.s    plr_notagain        ;no.
  1019. ; -------- CHANGE SECTION ------------------------------------------------
  1020.         move.w    mmd_psecnum(a2),d0    ;get section number
  1021.         addq.w    #1,d0            ;increase..
  1022.         cmp.w    msng_songlen(a4),d0    ;highest section?
  1023.         blt.s    plr_nohisec
  1024.         moveq    #0,d0            ;yes.
  1025. plr_nohisec    move.w    d0,mmd_psecnum(a2)    ;push back.
  1026.         add.w    d0,d0
  1027.         movea.l    msng_sections(a4),a0    ;section table
  1028.         move.w    0(a0,d0.w),d0        ;new playseqlist number
  1029.         add.w    d0,d0
  1030.         add.w    d0,d0
  1031.         move.w    d0,mmd_pseq(a2)
  1032.         movea.l    0(a1,d0.w),a0        ;a0 = ptr to new PlaySeq
  1033.         moveq    #0,d0            ;playseq OFFSET = 0
  1034. ; -------- FETCH BLOCK NUMBER FROM SEQUENCE ------------------------------
  1035. plr_notagain    move.w    d0,mmd_pseqnum(a2)    ;remember new playseq pos
  1036.         add.w    d0,d0
  1037.         move.w    42(a0,d0.w),d0        ;get number of the block
  1038.         bpl.s    plr_changeblk    ;neg. values for future expansion
  1039.         bra.s    plr_skipseq    ;(skip them)
  1040. ; ********* BELOW CODE FOR MMD0/MMD1 ONLY *******************************
  1041. plr_noMMD2_0    move.w    mmd_pseqnum(a2),d0    ;get play sequence number
  1042.         tst.b    nextblock-DB(a6)
  1043.         bmi.s    plr_noadvseq_b        ;Bxx sets nextblock to -1
  1044.         addq.w    #1,d0            ;advance sequence number
  1045. plr_noadvseq_b    cmp.w    msng_songlen(a4),d0    ;is this the highest seq number??
  1046.         blt.s    plr_notagain_b        ;no.
  1047.         moveq    #0,d0            ;yes: restart song
  1048. plr_notagain_b    move.b    d0,mmd_pseqnum+1(a2)    ;remember new playseq-#
  1049.         lea    msng_playseq(a4),a0    ;offset of sequence table
  1050.         move.b    0(a0,d0.w),d0        ;get number of the block
  1051. ; ********* BELOW CODE FOR BOTH FORMATS *********************************
  1052. plr_changeblk
  1053.     IFNE    CHECK
  1054.         cmp.w    msng_numblocks(a4),d0    ;beyond last block??
  1055.         blt.s    plr_nolstblk        ;no..
  1056.         moveq    #0,d0            ;play block 0
  1057.     ENDC
  1058. plr_nolstblk    move.w    d0,mmd_pblock(a2)    ;store block number
  1059. plr_nonewseq    clr.w    nextblock-DB(a6)     ;clear this if F00 set it
  1060. ; ------------------------------------------------------------------------
  1061. plr_nochgblock    move.w    d1,mmd_pline(a2)    ;set new line number
  1062.  
  1063.     IFNE    HOLD
  1064.         lea    trackdataptrs-DB(a6),a5
  1065.         move.w    mmd_pblock(a2),d0    ;pblock
  1066.         bsr.w    GetBlockAddr
  1067.         move.w    mmd_pline(a2),d0    ;play line
  1068.         move.b    msng_tempo2(a4),d3    ;interrupts/note
  1069.     IFNE    PLAYMMD0
  1070.         cmp.b    #'1',3(a2)
  1071.         bge.s    plr_mmd1_2
  1072.         move.b    (a0),d7            ;# of tracks
  1073.         move.w    d0,d1
  1074.         add.w    d0,d0    ;d0 * 2
  1075.         add.w    d1,d0    ;+ d0 = d0 * 3
  1076.         mulu    d7,d0
  1077.         lea    2(a0,d0.w),a3
  1078.         subq.b    #1,d7
  1079. plr_chkholdb    movea.l    (a5)+,a1        ;track data
  1080.         tst.b    trk_noteoffcnt(a1)    ;hold??
  1081.         bmi.s    plr_holdendb        ;no.
  1082.         move.b    (a3),d1            ;get the 1st byte..
  1083.         bne.s    plr_hold1b
  1084.         move.b    1(a3),d1
  1085.         and.b    #$f0,d1
  1086.         beq.s    plr_holdendb        ;don't hold
  1087.         bra.s    plr_hold2b
  1088. plr_hold1b    and.b    #$3f,d1            ;note??
  1089.         beq.s    plr_hold2b        ;no, cont hold..
  1090.         move.b    1(a3),d1
  1091.         and.b    #$0f,d1            ;get cmd
  1092.         subq.b    #3,d1            ;is there command 3 (slide)
  1093.         bne.s    plr_holdendb        ;no -> end holding
  1094. plr_hold2b    add.b    d3,trk_noteoffcnt(a1)    ;continue holding...
  1095. plr_holdendb    addq.l    #3,a3        ;next note
  1096.         dbf    d7,plr_chkholdb
  1097.         rts
  1098. plr_mmd1_2
  1099.     ENDC
  1100.         move.w    (a0),d7        ;# of tracks
  1101.         add.w    d0,d0
  1102.         add.w    d0,d0        ;d0 = d0 * 4
  1103.         mulu    d7,d0
  1104.         lea    8(a0,d0.l),a3
  1105.         subq.b    #1,d7
  1106. plr_chkhold    movea.l    (a5)+,a1        ;track data
  1107.         tst.b    trk_noteoffcnt(a1)    ;hold??
  1108.         bmi.s    plr_holdend        ;no.
  1109.         move.b    (a3),d1            ;get the 1st byte..
  1110.         bne.s    plr_hold1
  1111.         move.b    1(a3),d0
  1112.         and.b    #$3F,d0
  1113.         beq.s    plr_holdend        ;don't hold
  1114.         bra.s    plr_hold2
  1115. plr_hold1    and.b    #$7f,d1            ;note??
  1116.         beq.s    plr_hold2        ;no, cont hold..
  1117.         move.b    2(a3),d1
  1118.         subq.b    #3,d1            ;is there command 3 (slide)
  1119.         bne.s    plr_holdend        ;no -> end holding
  1120. plr_hold2    add.b    d3,trk_noteoffcnt(a1)    ;continue holding...
  1121. plr_holdend    addq.l    #4,a3        ;next note
  1122.         dbf    d7,plr_chkhold
  1123.     ENDC
  1124.         rts
  1125.  
  1126. ; *******************************************************************
  1127. ; DoPreFXLoop:    Loop and call DoPreFX
  1128. ; *******************************************************************
  1129. DoPreFXLoop:
  1130. ; -------- PRE-FX COMMAND HANDLING LOOP ----------------------------------
  1131.         moveq    #0,d5    ;command page count
  1132. plr_loop1    move.w    mmd_pblock(a2),d0
  1133.         bsr.w    GetBlockAddr
  1134.         move.w    d5,d1
  1135.         move.w    mmd_pline(a2),d2
  1136.         bsr.w    GetCmdPointer
  1137.         movea.l    a0,a3
  1138.         moveq    #0,d7    ;clear track count
  1139.         lea    trackdataptrs-DB(a6),a1
  1140. plr_loop1_1    movea.l    (a1)+,a5
  1141.         move.b    (a3),d0            ;command #
  1142.         beq.s    plr_loop1_end
  1143.         moveq    #0,d4
  1144.         move.b    1(a3),d4        ;data byte
  1145.     IFNE    PLAYMMD0
  1146.         cmp.b    #3,d6            ;if adv == 3 -> MMD0
  1147.         bne.s    doprefx_mmd12mask
  1148.         and.w    #$0F,d0
  1149.         bra.s    doprefx_mmd0maskd
  1150. doprefx_mmd12mask
  1151.     ENDC
  1152.         and.w    #$3F,d0
  1153. doprefx_mmd0maskd
  1154.         bsr.s    DoPreFX
  1155.         or.b    d0,trk_fxtype(a5)
  1156. plr_loop1_end    adda.w    d6,a3            ;next track...
  1157.         addq.w    #1,d7
  1158.         cmp.w    numtracks-DB(a6),d7
  1159.         blt.s    plr_loop1_1
  1160.         addq.w    #1,d5
  1161.         cmp.w    numpages-DB(a6),d5
  1162.         bls.s    plr_loop1
  1163.         rts
  1164.  
  1165. ; *******************************************************************
  1166. ; DoPreFX: Perform effects that must be handled before note playing
  1167. ; *******************************************************************
  1168. ; args:        a6 = DB            d0 = command number (w)
  1169. ;        a5 = track data        d5 = note number
  1170. ;        a4 = song        d4 = data
  1171. ;                    d7 = track #
  1172. ; returns:    d0 = 0: play - d0 = 1: don't play
  1173.  
  1174. rtplay        MACRO
  1175.         moveq    #0,d0
  1176.         rts
  1177.         ENDM
  1178. rtnoplay    MACRO
  1179.         moveq    #1,d0
  1180.         rts
  1181.         ENDM
  1182.  
  1183. DoPreFX:    add.b    d0,d0    ;* 2
  1184.         move.w    f_table(pc,d0.w),d0
  1185.         jmp    fst(pc,d0.w)
  1186. fst
  1187. f_table        dc.w    fx-fst,fx-fst,fx-fst,f_03-fst,fx-fst,fx-fst,fx-fst,fx-fst
  1188.         dc.w    f_08-fst,f_09-fst,fx-fst,f_0b-fst,f_0c-fst,fx-fst,f_0e-fst,f_0f-fst
  1189.         dc.w    fx-fst,fx-fst,fx-fst,fx-fst,fx-fst,f_15-fst,f_16-fst,fx-fst
  1190.         dc.w    fx-fst,f_19-fst,fx-fst,fx-fst,f_1c-fst,f_1d-fst,f_1e-fst,f_1f-fst
  1191.         dc.w    fx-fst,fx-fst,fx-fst,fx-fst,fx-fst,fx-fst,fx-fst,fx-fst
  1192.         dc.w    fx-fst,fx-fst,fx-fst,fx-fst,fx-fst,fx-fst,fx-fst,fx-fst
  1193.         dc.w    fx-fst,fx-fst,fx-fst,fx-fst,fx-fst,fx-fst,fx-fst,fx-fst
  1194.         dc.w    fx-fst,fx-fst,fx-fst,fx-fst,fx-fst,fx-fst,fx-fst,fx-fst
  1195. ; ---------------- tempo (F)
  1196. f_0f        tst.b    d4        ;test effect qual..
  1197.         beq    fx0fchgblck    ;if effect qualifier (last 2 #'s)..
  1198.         cmp.b    #$f0,d4        ;..is zero, go to next block
  1199.         bhi.s    fx0fspecial    ;if it's F1-FF something special
  1200. ; ---------------- just an ordinary "change tempo"-request
  1201.     IFNE    CIAB
  1202.         moveq    #0,d0        ;will happen!!!
  1203.         move.b    d4,d0
  1204.         bsr    _SetTempo    ;change The Tempo
  1205.     ENDC
  1206. fx        rtplay
  1207. ; ---------------- no, it was FFx, something special will happen!!
  1208. fx0fspecial:    cmp.b    #$f2,d4
  1209.         beq.s    f_1f
  1210.         cmp.b    #$f4,d4
  1211.         beq.s    f_1f
  1212.         cmp.b    #$f5,d4
  1213.         bne.s    isfxfe
  1214. ; ---------------- FF2 (or 1Fxx)
  1215. f_1f
  1216.     IFNE    HOLD
  1217.         move.b    trk_inithold(a5),trk_noteoffcnt(a5) ;initialize hold
  1218.         bne.s    f_1frts            ;not 0 -> OK
  1219.         st    trk_noteoffcnt(a5)    ;0 -> hold = 0xff (-1)
  1220.     ENDC
  1221. f_1frts        rtnoplay
  1222. isfxfe:        cmp.b    #$fe,d4
  1223.         bne.s    notcmdfe
  1224. ; ---------------- it was FFE, stop playing
  1225.         clr.w    mmd_pstate(a2)
  1226.     IFNE    CIAB
  1227.         movea.l    craddr-DB(a6),a0
  1228.         bclr    #0,(a0)
  1229.     ENDC
  1230.         bsr.w    SoundOff
  1231.     IFNE    AURA
  1232.         jsr    _RemAura(pc)
  1233.     ENDC
  1234.         adda.w    #8,sp    ;2 subroutine levels
  1235.         bra.w    plr_exit
  1236. f_ffe_no8    rtplay
  1237. notcmdfe:    cmp.b    #$fd,d4 ;change period
  1238.         bne.s    isfxff
  1239. ; ---------------- FFD, change the period, don't replay the note
  1240.     IFNE    CHECK
  1241.         cmp.w    #4,d7 ;no tracks above 4, thank you!!
  1242.         bge.s    f_0f_rts
  1243.     ENDC
  1244.         move.l    trk_periodtbl(a5),d1    ;period table
  1245.         beq.s    f_1frts
  1246.         movea.l    d1,a0
  1247.         move.b    trk_currnote(a5),d0
  1248.         subq.b    #1,d0    ;sub 1 to make "real" note number
  1249.     IFNE    CHECK
  1250.         bmi.s    f_1frts
  1251.     ENDC
  1252.         add.b    msng_playtransp(a4),d0
  1253.         add.b    trk_stransp(a5),d0
  1254.         add.w    d0,d0
  1255.         bmi.s    f_1frts
  1256.         move.w    0(a0,d0.w),trk_prevper(a5) ;get & push the period
  1257.         rtnoplay
  1258. isfxff        cmp.b    #$ff,d4        ;note off??
  1259.         bne.s    isfxf7
  1260.         move.w    d7,d0
  1261.         move.l    a1,-(sp)
  1262.         bsr.w    _ChannelOff
  1263.         move.l    (sp)+,a1
  1264.         rtplay
  1265. isfxf7
  1266.     IFNE    MIDI
  1267.         cmp.b    #$f7,d4        ;wait SysX
  1268.         bne.s    f_0f_rts
  1269.         tst.b    sysx-DB(a6)
  1270.         beq.s    f_0f_rts
  1271.         move.w    #2,blkdelay-DB(a6)
  1272.     ENDC
  1273. f_0f_rts    rtplay
  1274. ; ---------------- F00, called Pattern Break in ST
  1275. fx0fchgblck:    move.b    #1,nextblock-DB(a6) ;next block????...YES!!!! (F00)
  1276.         bra.s    f_0f_rts
  1277. ; ---------------- was not Fxx, then it's something else!!
  1278. f_0e
  1279.     IFNE    CHECK
  1280.         cmp.b    #4,d7
  1281.         bge.s    f_0e_rts
  1282.     ENDC
  1283.         bset    #0,trk_miscflags(a5)
  1284.         move.b    d4,trk_wfcmd+1(a5) ;set waveform command position ptr
  1285. f_0e_rts    rtplay
  1286. ; ---------------- change volume
  1287. f_0c        move.b    d4,d0
  1288.         bpl.s    plr_nosetdefvol
  1289.         and.b    #$7F,d0
  1290.     IFNE    CHECK
  1291.         cmp.b    #64,d0
  1292.         bgt.s    go_nocmd
  1293.     ENDC
  1294.         moveq    #0,d1
  1295.         move.b    trk_previnstr(a5),d1
  1296.         asl.w    #3,d1
  1297.         move.b    d0,inst_svol(a4,d1.w)    ;set new svol
  1298.         bra.s    plr_setvol
  1299. plr_nosetdefvol    btst    #4,msng_flags(a4)    ;look at flags
  1300.         bne.s    volhex
  1301.         lsr.b    #4,d0        ;get number from left
  1302.         mulu    #10,d0        ;number of tens
  1303.         move.b    d4,d1        ;get again
  1304.         and.b    #$0f,d1        ;this time don't get tens
  1305.         add.b    d1,d0        ;add them
  1306. volhex:
  1307.     IFNE    CHECK
  1308.         cmp.b    #64,d0
  1309.         bhi.s    go_nocmd
  1310.     ENDC
  1311. plr_setvol    move.b    d0,trk_prevvol(a5)
  1312. go_nocmd    rtplay
  1313. ; ---------------- tempo2 change??
  1314. f_09
  1315.     IFNE    CHECK
  1316.         and.b    #$1F,d4
  1317.         bne.s    fx9chk
  1318.         moveq    #$20,d4
  1319.     ENDC
  1320. fx9chk:        move.b    d4,msng_tempo2(a4)
  1321. f_09_rts    rtplay
  1322. ; ---------------- block delay
  1323. f_1e        tst.w    blkdelay-DB(a6)
  1324.         bne.s    f_1e_rts
  1325.         addq.w    #1,d4
  1326.         move.w    d4,blkdelay-DB(a6)
  1327. f_1e_rts    rtplay
  1328. ; ---------------- finetune
  1329. f_15
  1330.     IFNE    CHECK
  1331.         cmp.b    #7,d4
  1332.         bgt.s    f_15_rts
  1333.         cmp.b    #-8,d4
  1334.         blt.s    f_15_rts
  1335.     ENDC
  1336.         move.b    d4,trk_finetune(a5)
  1337. f_15_rts    rtplay
  1338. ; ---------------- repeat loop
  1339. f_16        tst.b    d4
  1340.         bne.s    plr_dorpt
  1341.         move.w    mmd_pline(a2),rptline-DB(a6)
  1342.         bra.s    f_16_rts
  1343. plr_dorpt    tst.w    rptcounter-DB(a6)
  1344.         beq.s    plr_newrpt
  1345.         subq.w    #1,rptcounter-DB(a6)
  1346.         beq.s    f_16_rts
  1347.         bra.s    plr_setrptline
  1348. plr_newrpt    move.b    d4,rptcounter+1-DB(a6)
  1349. plr_setrptline    move.w    rptline-DB(a6),d0
  1350.         addq.w    #1,d0
  1351.         move.w    d0,nextblockline-DB(a6)
  1352. f_16_rts    rtplay
  1353. ; ---------------- preset change
  1354. f_1c        cmp.b    #$80,d4
  1355.         bhi.s    f_1c_rts
  1356.         moveq    #0,d1
  1357.         move.b    trk_previnstr(a5),d1
  1358.         add.w    d1,d1
  1359.         lea    ext_midipsets-DB(a6),a0
  1360.         ext.w    d4
  1361.         move.w    d4,0(a0,d1.w)        ;set MIDI preset
  1362. f_1c_rts    rtplay
  1363. ; ---------------- note off time set??
  1364. f_08
  1365.     IFNE    HOLD
  1366.         move.b    d4,d0
  1367.         lsr.b    #4,d4        ;extract left  nibble
  1368.         and.b    #$0f,d0        ; "   "  right  "  "
  1369.         move.b    d4,trk_initdecay(a5)    ;left = decay
  1370.         move.b    d0,trk_inithold(a5)    ;right = hold
  1371.     ENDC
  1372.         rtplay
  1373. ; ---------------- sample begin offset
  1374. f_19        lsl.w    #8,d4
  1375.         move.w    d4,trk_soffset(a5)
  1376. f_19_rts    rtplay
  1377. ; ---------------- cmd Bxx, "position jump"
  1378. f_0b
  1379.     IFNE    CHECK
  1380.         cmp.b    #'2',3(a2)
  1381.         bcc.s    chk0b_mmd2
  1382.         cmp.w    msng_songlen(a4),d4
  1383.         bhi.s    f_0b_rts
  1384.         bra.s    chk0b_end
  1385. chk0b_mmd2    move.w    mmd_pseq(a2),d0        ;get seq number
  1386.         movea.l    msng_pseqs(a4),a0    ;ptr to playseqs
  1387.         movea.l    0(a0,d0.w),a0        ;a0 = ptr to curr PlaySeq
  1388.         cmp.w    40(a0),d4        ;test song length
  1389.         bhi.s    f_0b_rts
  1390. chk0b_end
  1391.     ENDC
  1392.         move.w    d4,mmd_pseqnum(a2)
  1393.         st    nextblock-DB(a6)    ; = 1
  1394. f_0b_rts    rtplay
  1395. ; ---------------- cmd 1Dxx, jump to next seq, line # specified
  1396. f_1d        move.w    #$1ff,nextblock-DB(a6)
  1397.         addq.w    #1,d4
  1398.         move.w    d4,nextblockline-DB(a6)
  1399.         rtplay
  1400. ; ---------------- try portamento (3)
  1401. f_03
  1402.     IFNE    CHECK
  1403.         cmp.w    #4,d7
  1404.         bge.s    f_03_rts
  1405.     ENDC
  1406.         moveq    #0,d0
  1407.         move.b    trk_currnote(a5),d0
  1408.         subq.b    #1,d0        ;subtract note number
  1409.         bmi.s    plr_setfx3spd    ;0 -> set new speed
  1410.         move.l    trk_periodtbl(a5),d1
  1411.         beq.s    f_03_rts
  1412.         movea.l    d1,a0
  1413.         add.b    msng_playtransp(a4),d0    ;play transpose
  1414.         add.b    trk_stransp(a5),d0 ;and instrument transpose
  1415.         bmi.s    f_03_rts    ;again.. too low
  1416.         add.w    d0,d0
  1417.         move.w    0(a0,d0.w),trk_porttrgper(a5) ;period of this note is the target
  1418. plr_setfx3spd:    tst.b    d4        ;qual??
  1419.         beq.s    f_03_rts    ;0 -> do nothing
  1420.         move.b    d4,trk_prevportspd(a5)    ;store speed
  1421. f_03_rts    rtnoplay
  1422.  
  1423. ; *******************************************************************
  1424. ; DoFX: Handle effects, hold/fade etc.
  1425. ; *******************************************************************
  1426. DoFX        moveq    #0,d3
  1427.         move.b    mmd_counter(a2),d3
  1428.     IFNE    HOLD
  1429.         lea    trackdataptrs-DB(a6),a1
  1430. ; Loop 1: Hold/Fade handling
  1431.         moveq    #0,d7    ;clear track count
  1432. dofx_loop1    movea.l    (a1)+,a5
  1433.         bsr.w    HoldAndFade
  1434.         addq.w    #1,d7
  1435.         cmp.w    numtracks-DB(a6),d7
  1436.         blt.s    dofx_loop1
  1437.     ENDC
  1438. ; Loop 2: Track command handling
  1439.         moveq    #0,d5    ;command page count
  1440. dofx_loop2    move.w    fxplineblk-DB(a6),d0
  1441.         bsr.w    GetBlockAddr
  1442.         movea.l    a0,a3
  1443.     IFNE    PLAYMMD0
  1444.         cmp.b    #'1',3(a2)
  1445.         bge.s    dofx_sbd_nommd0
  1446.         bsr.w    StoreBlkDimsMMD0
  1447.         bra.s    dofx_sbd_mmd0
  1448. dofx_sbd_nommd0
  1449.     ENDC
  1450.         bsr.w    StoreBlockDims
  1451. dofx_sbd_mmd0    move.w    d5,d1
  1452.         move.w    fxplineblk+2-DB(a6),d2
  1453.         movea.l    a3,a0
  1454.         bsr.s    GetCmdPointer
  1455.         movea.l    a0,a3
  1456.         moveq    #0,d7    ;clear track count
  1457.         lea    trackdataptrs-DB(a6),a1
  1458. dofx_loop2_1    movea.l    (a1)+,a5
  1459.         moveq    #0,d4
  1460.         move.b    (a3),d0            ;command #
  1461.         move.b    1(a3),d4        ;data byte
  1462.     IFNE    PLAYMMD0
  1463.         cmp.b    #3,d6            ;if adv == 3 -> MMD0
  1464.         bne.s    dofx_mmd12mask
  1465.         and.w    #$0F,d0
  1466.         bra.s    dofx_mmd0maskd
  1467. dofx_mmd12mask
  1468.     ENDC
  1469.         and.w    #$1F,d0
  1470. dofx_mmd0maskd    tst.b    trk_fxtype(a5)
  1471.         bgt.s    dofx_lend2_1    ;1 = skip
  1472.     IFNE    MIDI
  1473.         beq.s    dofx_chfx
  1474.         bsr.w    MIDIFX
  1475.         bra.s    dofx_lend2_1
  1476.     ENDC
  1477.     IFEQ    MIDI
  1478.         bne.s    dofx_lend2_1
  1479.     ENDC
  1480. dofx_chfx    bsr.w    ChannelFX
  1481. dofx_lend2_1    adda.w    d6,a3            ;next track...
  1482.         addq.w    #1,d7
  1483.         cmp.w    numtracks-DB(a6),d7
  1484.         blt.s    dofx_loop2_1
  1485.         addq.w    #1,d5
  1486.         cmp.w    numpages-DB(a6),d5
  1487.         bls.s    dofx_loop2
  1488. ; Loop 3: Updating audio hardware
  1489.         moveq    #0,d7    ;clear track count
  1490.         lea    trackdataptrs-DB(a6),a1
  1491. dofx_loop3    movea.l    (a1)+,a5
  1492.     IFNE    HOLD
  1493.         tst.b    trk_fxtype(a5)
  1494.         bne.s    dofx_lend3    ;only in case 0 (norm)
  1495.     ENDC
  1496.     IFEQ    HOLD
  1497.         cmp.w    #4,d7
  1498.         bge.s    dofx_stopl3
  1499.     ENDC
  1500.         bsr.w    UpdatePerVol
  1501. dofx_lend3    addq.w    #1,d7
  1502.         cmp.w    numtracks-DB(a6),d7
  1503.         blt.s    dofx_loop3
  1504. dofx_stopl3    rts
  1505.  
  1506. ; *******************************************************************
  1507. ; GetCmdPointer: Return command pointer for track 0
  1508. ; *******************************************************************
  1509. ; args:        a0 = block pointer
  1510. ;        d1 = page number
  1511. ;        d2 = line number
  1512. ;        a2 = module
  1513. ; result:    a0 = command pointer (i.e. trk 0 note + 2)
  1514. ;        d6 = track advance (bytes)
  1515. ; scratches:    d0, d1, d2, a0
  1516. ; Note: no num_pages check! If numpages > 0 it can be assumed that
  1517. ; extra pages exist.
  1518.  
  1519. GetCmdPointer
  1520.     IFNE    PLAYMMD0
  1521.         cmp.b    #'1',3(a2)
  1522.         blt.s    GetCmdPtrMMD0
  1523.     ENDC
  1524.         mulu    (a0),d2        ;d2 = line # * numtracks
  1525.         add.l    d2,d2        ;d2 *= 2...
  1526.         subq.w    #1,d1
  1527.         bmi.s    gcp_page0
  1528.         movea.l    4(a0),a0
  1529.         movea.l    12(a0),a0
  1530.         add.w    d1,d1
  1531.         add.w    d1,d1
  1532.         movea.l    4(a0,d1.w),a0    ;command data
  1533.         adda.l    d2,a0
  1534.         moveq    #2,d6
  1535.         rts
  1536. gcp_page0    add.l    d2,d2        ;d2 *= 4
  1537.         lea    10(a0,d2.l),a0    ;offs: 4 = header, 2 = note
  1538.         moveq    #4,d6        ;track advance (bytes)
  1539.         rts
  1540.     IFNE    PLAYMMD0
  1541. GetCmdPtrMMD0    moveq    #0,d0
  1542.         move.b    (a0),d0        ;get numtracks
  1543.         mulu    d0,d2        ;line # * numtracks
  1544.         move.w    d2,d0
  1545.         add.w    d2,d2
  1546.         add.w    d0,d2        ; *= 3...
  1547.         lea    3(a0,d2.l),a0    ;offs: 2 = header, 1 = note
  1548.         moveq    #3,d6
  1549.         rts
  1550.     ENDC
  1551.  
  1552. ; *******************************************************************
  1553. ; GetBlockAddr: Return pointer to block
  1554. ; *******************************************************************
  1555. ; args:        d0 = block number
  1556. ; result:    a0 = block pointer
  1557. ; scratches: d0, a0
  1558.  
  1559. GetBlockAddr    movea.l    mmd_blockarr(a2),a0
  1560.         add.w    d0,d0
  1561.         add.w    d0,d0
  1562.         movea.l    0(a0,d0.w),a0
  1563.         rts
  1564.  
  1565. ; *******************************************************************
  1566. ; GetNoteDataAddr: Check & return addr. of current note
  1567. ; *******************************************************************
  1568. ;args:        d0 = pblock        a6 = DB
  1569. ;returns:    a3 = address
  1570. ;scratches:    d0, a0, d1
  1571.  
  1572. GetNoteDataAddr    bsr.w    GetBlockAddr
  1573.         movea.l    a0,a3
  1574.     IFNE    PLAYMMD0
  1575.         cmp.b    #'1',3(a2)
  1576.         blt.s    GetNDAddrMMD0
  1577.     ENDC
  1578.         bsr.w    StoreBlockDims
  1579.         move.w    numlines-DB(a6),d1
  1580.         move.w    mmd_pline(a2),d0
  1581.         cmp.w    d1,d0        ;check if block end exceeded...
  1582.         bls.s    plr_nolinex
  1583.         move.w    d1,d0
  1584. plr_nolinex    add.w    d0,d0
  1585.         add.w    d0,d0    ;d0 = d0 * 4
  1586.         mulu    numtracks-DB(a6),d0
  1587.         lea    8(a3,d0.l),a3    ;address of current note
  1588.         rts
  1589.  
  1590.     IFNE    PLAYMMD0
  1591. GetNDAddrMMD0    bsr.w    StoreBlkDimsMMD0
  1592.         move.w    numlines-DB(a6),d1
  1593.         move.w    mmd_pline(a2),d0
  1594.         cmp.w    d1,d0        ;check if block end exceeded...
  1595.         bls.s    plr_nolinex2
  1596.         move.w    d1,d0
  1597. plr_nolinex2    move.w    d0,d1
  1598.         add.w    d0,d0
  1599.         add.w    d1,d0    ;d0 = d0 * 3
  1600.         mulu    numtracks-DB(a6),d0
  1601.         lea    2(a3,d0.l),a3    ;address of current note
  1602.         rts
  1603.     ENDC
  1604.  
  1605. ; *******************************************************************
  1606. ; StoreBlockDims: Store block dimensions
  1607. ; *******************************************************************
  1608. ; args:        a0 = block ptr, a6 = DB
  1609.  
  1610. StoreBlockDims    move.l    (a0)+,numtracks-DB(a6)    ;numtracks & lines
  1611.         tst.l    (a0)            :BlockInfo
  1612.         beq.s    sbd_1page
  1613.         movea.l    (a0),a0
  1614.         move.l    12(a0),d0        ;BlockInfo.pagetable
  1615.         beq.s    sbd_1page
  1616.         movea.l    d0,a0
  1617.         move.w    (a0),numpages-DB(a6)    ;num_pages
  1618.         rts
  1619. sbd_1page    clr.w    numpages-DB(a6)
  1620.         rts
  1621.  
  1622.     IFNE    PLAYMMD0
  1623. StoreBlkDimsMMD0
  1624.         clr.w    numpages-DB(a6)
  1625.         moveq    #0,d0
  1626.         move.b    (a0)+,d0        ;numtracks
  1627.         move.w    d0,numtracks-DB(a6)
  1628.         move.b    (a0),d0            ;numlines
  1629.         move.w    d0,numlines-DB(a6)
  1630.         rts
  1631.     ENDC
  1632.  
  1633. ; *******************************************************************
  1634. ; HoldAndFade: Handle hold/fade
  1635. ; *******************************************************************
  1636. ; args:        a5 = track data
  1637. ;        a6 = DB
  1638. ;        d7 = track #
  1639. ; scratches:    d0, d1, a0
  1640.  
  1641.     IFNE    HOLD
  1642. HoldAndFade
  1643.     IFNE    MIDI
  1644.         tst.b    trk_prevmidin(a5)    ;is it MIDI??
  1645.         bne.w    plr_haf_midi
  1646.     ENDC
  1647.     IFNE    CHECK
  1648.         cmp.w    #4,d7
  1649.         bge.w    plr_haf_midi    ;no non-MIDI effects in tracks 4 - 15
  1650.     ENDC
  1651.         tst.b    trk_noteoffcnt(a5)
  1652.         bmi.s    plr_haf_noholdexp
  1653.         subq.b    #1,trk_noteoffcnt(a5)
  1654.         bpl.s    plr_haf_noholdexp
  1655.     IFNE    SYNTH
  1656.         tst.b    trk_synthtype(a5)        ;synth/hybrid??
  1657.         beq.s    plr_nosyndec
  1658.         move.b    trk_decay(a5),trk_volcmd+1(a5)    ;set volume command pointer
  1659.         clr.b    trk_volwait(a5)            ;abort WAI
  1660.         bra.s    plr_haf_noholdexp
  1661.     ENDC
  1662. plr_nosyndec    move.b    trk_decay(a5),trk_fadespd(a5)    ;set fade...
  1663.         bne.s    plr_haf_noholdexp        ;if > 0, don't stop sound
  1664.         moveq    #0,d0
  1665.         bset    d7,d0
  1666.         move.w    d0,$dff096            ;shut DMA...
  1667. plr_haf_noholdexp
  1668.         move.b    trk_fadespd(a5),d0    ;fade??
  1669.         beq.s    plr_haf_dofx        ;no.
  1670.         sub.b    d0,trk_prevvol(a5)
  1671.         bpl.s    plr_nofade2low
  1672.         clr.b    trk_prevvol(a5)
  1673.         clr.b    trk_fadespd(a5)        ;fade no more
  1674. plr_nofade2low
  1675. plr_haf_dofx    clr.b    trk_fxtype(a5)
  1676. plr_haf_rts    rts
  1677. ; MIDI version
  1678. plr_haf_midi
  1679.         st    trk_fxtype(a5)
  1680.     IFNE    MIDI
  1681.         tst.b    trk_noteoffcnt(a5)
  1682.         bmi.s    plr_haf_rts
  1683.         subq.b    #1,trk_noteoffcnt(a5)
  1684.         bpl.s    plr_haf_rts
  1685.         move.b    trk_prevmidin(a5),d1
  1686.         beq.s    plr_haf_rts
  1687.         lea    noteondata-DB(a6),a0
  1688.         exg.l    a5,a1
  1689.         bsr.w    choff_midi
  1690.         exg.l    a5,a1
  1691.     ENDC
  1692.         rts
  1693. ;hold
  1694.     ENDC
  1695.  
  1696. ; *******************************************************************
  1697. ; ChannelFX:    Do an effect on a channel
  1698. ; *******************************************************************
  1699. ;args:                    d3 = counter
  1700. ;        a4 = song struct    d4 = command qual (long, byte used)
  1701. ;        a5 = track data ptr    
  1702. ;        a6 = DB            d0 = command (long, byte used)
  1703. ;                    d7 = track (channel) number
  1704. ;scratches: d0, d1, d4, a0
  1705.  
  1706. ChannelFX    add.b    d0,d0    ;* 2
  1707.         move.w    fx_table(pc,d0.w),d0
  1708.         jmp    fxs(pc,d0.w)
  1709. fx_table    dc.w    fx_00-fxs,fx_01-fxs,fx_02-fxs,fx_03-fxs,fx_04-fxs
  1710.         dc.w    fx_05-fxs,fx_06-fxs,fx_07-fxs,fx_xx-fxs,fx_xx-fxs
  1711.         dc.w    fx_0a-fxs,fx_xx-fxs,fx_0c-fxs,fx_0d-fxs,fx_xx-fxs
  1712.         dc.w    fx_0f-fxs
  1713.         dc.w    fx_10-fxs,fx_11-fxs,fx_12-fxs,fx_13-fxs,fx_14-fxs
  1714.         dc.w    fx_xx-fxs,fx_xx-fxs,fx_xx-fxs,fx_18-fxs,fx_xx-fxs
  1715.         dc.w    fx_1a-fxs,fx_1b-fxs,fx_xx-fxs,fx_xx-fxs,fx_xx-fxs
  1716.         dc.w    fx_1f-fxs
  1717. fxs:
  1718. ;    **************************************** Effect 01 ******
  1719. fx_01        tst.b    d3
  1720.         bne.s    fx_01nocnt0
  1721.         btst    #5,msng_flags(a4)    ;FLAG_STSLIDE??
  1722.         bne.s    fx_01rts
  1723. fx_01nocnt0    move.w    trk_prevper(a5),d0
  1724.         sub.w    d4,d0
  1725.         cmp.w    #113,d0
  1726.         bge.s    fx_01noovf
  1727.         move.w    #113,d0
  1728. fx_01noovf    move.w    d0,trk_prevper(a5)
  1729. fx_xx        ;fx_xx is just a RTS
  1730. fx_01rts    rts
  1731. ;    **************************************** Effect 11 ******
  1732. fx_11        tst.b    d3
  1733.         bne.s    fx_11rts
  1734.         sub.w    d4,trk_prevper(a5)
  1735. fx_11rts    rts
  1736. ;    **************************************** Effect 02 ******
  1737. fx_02        tst.b    d3
  1738.         bne.s    fx_02nocnt0
  1739.         btst    #5,msng_flags(a4)
  1740.         bne.s    fx_02rts
  1741. fx_02nocnt0    add.w    d4,trk_prevper(a5)
  1742. fx_02rts    rts
  1743. ;    **************************************** Effect 12 ******
  1744. fx_12        tst.b    d3
  1745.         bne.s    fx_12rts
  1746.         add.w    d4,trk_prevper(a5)
  1747. fx_12rts    rts
  1748. ;    **************************************** Effect 00 ******
  1749. fx_00        tst.b    d4    ;both fxqualifiers are 0s: no arpeggio
  1750.         beq.s    fx_00rts
  1751.         move.l    d3,d0
  1752.         divu    #3,d0
  1753.         swap    d0
  1754.         subq.b    #1,d0
  1755.         bgt.s    fx_arp2
  1756.         blt.s    fx_arp0
  1757.         and.b    #$0f,d4
  1758.         bra.s    fx_doarp
  1759. fx_arp0        lsr.b    #4,d4
  1760.         bra.s    fx_doarp
  1761. fx_arp2        moveq    #0,d4
  1762. fx_doarp:    move.b    (a5),d0
  1763.         subq.b    #1,d0        ;-1 to make it 0 - 127
  1764.         add.b    msng_playtransp(a4),d0    ;add play transpose
  1765.         add.b    trk_stransp(a5),d0    ;add instrument transpose
  1766.         add.b    d0,d4
  1767.         move.l    trk_periodtbl(a5),d1
  1768.         beq.s    fx_00rts
  1769.         movea.l    d1,a0
  1770.         add.b    d0,d0
  1771.         move.w    0(a0,d0.w),d0    ;base note period
  1772.         add.b    d4,d4
  1773.         sub.w    0(a0,d4.w),d0    ;calc difference from base note
  1774.         move.w    d0,trk_arpadjust(a5)
  1775. fx_00rts    rts
  1776. ;    **************************************** Effect 04 ******
  1777. fx_14        move.b    #6,trk_vibshift(a5)
  1778.         bra.s    vib_cont
  1779. fx_04        move.b    #5,trk_vibshift(a5)
  1780. vib_cont    tst.b    d3
  1781.         bne.s    nonvib
  1782.         move.b    d4,d1
  1783.         beq.s    nonvib
  1784.         and.w    #$0f,d1
  1785.         beq.s    plr_chgvibspd
  1786.         move.w    d1,trk_vibrsz(a5)
  1787. plr_chgvibspd    and.b    #$f0,d4
  1788.         beq.s    nonvib
  1789.         lsr.b    #3,d4
  1790.         and.b    #$3e,d4
  1791.         move.b    d4,trk_vibrspd(a5)
  1792. nonvib        move.b    trk_vibroffs(a5),d0
  1793.         lsr.b    #2,d0
  1794.         and.w    #$1f,d0
  1795.         moveq    #0,d1
  1796.         lea    sinetable(pc),a0
  1797.         move.b    0(a0,d0.w),d0
  1798.         ext.w    d0
  1799.         muls    trk_vibrsz(a5),d0
  1800.         move.b    trk_vibshift(a5),d1
  1801.         asr.w    d1,d0
  1802.         move.w    d0,trk_vibradjust(a5)
  1803.         move.b    trk_vibrspd(a5),d0
  1804.         add.b    d0,trk_vibroffs(a5)
  1805. fx_04rts    rts
  1806. ;    **************************************** Effect 06 ******
  1807. fx_06:        tst.b    d3
  1808.         bne.s    fx_06nocnt0
  1809.         btst    #5,msng_flags(a4)
  1810.         bne.s    fx_04rts
  1811. fx_06nocnt0    bsr.s    plr_volslide        ;Volume slide
  1812.         bra.s    nonvib            ;+ Vibrato
  1813. ;    **************************************** Effect 07 ******
  1814. fx_07        tst.b    d3
  1815.         bne.s    nontre
  1816.         move.b    d4,d1
  1817.         beq.s    nontre
  1818.         and.w    #$0f,d1
  1819.         beq.s    plr_chgtrespd
  1820.         move.w    d1,trk_tremsz(a5)
  1821. plr_chgtrespd    and.b    #$f0,d4
  1822.         beq.s    nontre
  1823.         lsr.b    #2,d4
  1824.         and.b    #$3e,d4
  1825.         move.b    d4,trk_tremspd(a5)
  1826. nontre        move.b    trk_tremoffs(a5),d0
  1827.         lsr.b    #3,d0
  1828.         and.w    #$1f,d0
  1829.         lea    sinetable(pc),a0
  1830.         move.b    0(a0,d0.w),d1
  1831.         ext.w    d1
  1832.         muls    trk_tremsz(a5),d1
  1833.         asr.w    #7,d1
  1834.         move.b    trk_tremspd(a5),d0
  1835.         add.b    d0,trk_tremoffs(a5)
  1836.         add.b    trk_prevvol(a5),d1
  1837.         bpl.s    tre_pos
  1838.         moveq    #0,d1
  1839. tre_pos        cmp.b    #64,d1
  1840.         ble.s    tre_no2hi
  1841.         moveq    #64,d1
  1842. tre_no2hi    move.b    d1,trk_tempvol(a5)
  1843.         rts
  1844. ;    ********* VOLUME SLIDE FUNCTION *************************
  1845. plr_volslide    move.b    d4,d0
  1846.         moveq    #0,d1
  1847.         move.b    trk_prevvol(a5),d1 ;move previous vol to d1
  1848.         and.b    #$f0,d0
  1849.         bne.s    crescendo
  1850.         sub.b    d4,d1    ;sub from prev. vol
  1851. voltest0    bpl.s    novolover64
  1852.         moveq    #0,d1    ;volumes under zero not accepted
  1853.         bra.s    novolover64
  1854. crescendo:    lsr.b    #4,d0
  1855.         add.b    d0,d1
  1856. voltest        cmp.b    #64,d1
  1857.         ble.s    novolover64
  1858.         moveq    #64,d1
  1859. novolover64    move.b    d1,trk_prevvol(a5)
  1860. volsl_rts    rts
  1861. ;    **************************************** Effect 0D/0A ***
  1862. fx_0a:
  1863. fx_0d:        tst.b    d3
  1864.         bne.s    plr_volslide
  1865.         btst    #5,msng_flags(a4)
  1866.         beq.s    plr_volslide
  1867.         rts
  1868. ;    **************************************** Effect 05 ******
  1869. fx_05:        tst.b    d3
  1870.         bne.s    fx_05nocnt0
  1871.         btst    #5,msng_flags(a4)
  1872.         bne.s    fx_05rts
  1873. fx_05nocnt0    bsr.s    plr_volslide
  1874.         bra.s    fx_03nocnt0
  1875. fx_05rts    rts
  1876. ;    **************************************** Effect 1A ******
  1877. fx_1a        tst.b    d3
  1878.         bne.s    volsl_rts
  1879.         move.b    trk_prevvol(a5),d1
  1880.         add.b    d4,d1
  1881.         bra.s    voltest
  1882. ;    **************************************** Effect 1B ******
  1883. fx_1b        tst.b    d3
  1884.         bne.s    volsl_rts
  1885.         move.b    trk_prevvol(a5),d1
  1886.         sub.b    d4,d1
  1887.         bra.s    voltest0
  1888. ;    **************************************** Effect 03 ******
  1889. fx_03        tst.b    d3
  1890.         bne.s    fx_03nocnt0
  1891.         btst    #5,msng_flags(a4)
  1892.         bne.s    fx_03rts
  1893. fx_03nocnt0    move.w    trk_porttrgper(a5),d0    ;d0 = target period
  1894.         beq.s    fx_03rts
  1895.         move.w    trk_prevper(a5),d1    ;d1 = curr. period
  1896.         move.b    trk_prevportspd(a5),d4    ;get prev. speed
  1897.         cmp.w    d0,d1
  1898.         bhi.s    subper    ;curr. period > target period
  1899.         add.w    d4,d1    ;add the period
  1900.         cmp.w    d0,d1
  1901.         bge.s    targreached
  1902.         bra.s    targnreach
  1903. subper:        sub.w    d4,d1    ;subtract
  1904.         cmp.w    d0,d1    ;compare current period to target period
  1905.         bgt.s    targnreach
  1906. targreached:    move.w    trk_porttrgper(a5),d1 ;eventually push target period
  1907.         clr.w    trk_porttrgper(a5) ;now we can forget everything
  1908. targnreach:    move.w    d1,trk_prevper(a5)
  1909. fx_03rts    rts
  1910. ;    **************************************** Effect 13 ******
  1911. fx_13:        cmp.b    #3,d3
  1912.         bge.s    fx_13rts    ;if counter < 3
  1913.         neg.w    d4
  1914.         move.w    d4,trk_vibradjust(a5)    ;subtract effect qual...
  1915. fx_13rts    rts
  1916. ;    *********************************************************
  1917. fx_0c:        tst.b    d3
  1918.         bne.s    fx_13rts
  1919. dvc_0        move.b    trk_prevvol(a5),d1
  1920.         rts
  1921. ;    **************************************** Effect 10 ******
  1922. fx_10:
  1923.     IFNE    MIDI
  1924.         tst.b    d3
  1925.         bne.s    fx_13rts
  1926.         move.w    d4,d0
  1927.         bra.w    _InitMIDIDump
  1928.     ENDC
  1929.     IFEQ    MIDI
  1930.         rts
  1931.     ENDC
  1932. ;    **************************************** Effect 18 ******
  1933. fx_18        cmp.b    d4,d3
  1934.         bne.s    fx_18rts
  1935.         clr.b    trk_prevvol(a5)
  1936. fx_18rts    rts
  1937. ;    **************************************** Effect 1F ******
  1938. fx_1f        move.b    d4,d1
  1939.         lsr.b    #4,d4        ;note delay
  1940.         beq.s    nonotedelay
  1941.         cmp.b    d4,d3        ;compare to counter
  1942.         blt.s    fx_18rts    ;tick not reached
  1943.         bne.s    nonotedelay
  1944.         bra    playfxnote    ;trigger note
  1945. nonotedelay    and.w    #$0f,d1        ;retrig?
  1946.         beq.s    fx_18rts
  1947.         moveq    #0,d0
  1948.         move.b    d3,d0
  1949.         divu    d1,d0
  1950.         swap    d0        ;get modulo of counter/tick
  1951.         tst.w    d0
  1952.         bne.s    fx_18rts
  1953.         bra    playfxnote    ;retrigger
  1954. ;    **************************************** Effect 0F ******
  1955. ;    see below...
  1956. ;    *********************************************************
  1957.  
  1958. ; *******************************************************************
  1959. ; UpdatePerVol:    Update audio registers (period & volume) after FX
  1960. ; *******************************************************************
  1961. ; args:        a6 = DB            d7 = channel #
  1962. ;        a5 = track data
  1963. ; scratches:    d0, d1, a0, d5
  1964. UpdatePerVol    move.w    trk_prevper(a5),d5
  1965.     IFNE    SYNTH
  1966.         move.l    trk_synthptr(a5),d0
  1967.         beq.s    plr_upv_nosynth
  1968.         move.l    a1,-(sp)
  1969.         bsr.w    synth_start
  1970.         move.l    (sp)+,a1
  1971.     ENDC
  1972. plr_upv_nosynth    add.w    trk_vibradjust(a5),d5
  1973.         sub.w    trk_arpadjust(a5),d5
  1974.         clr.l    trk_vibradjust(a5)    ;clr both adjusts
  1975.         movea.l    trk_audioaddr(a5),a0
  1976.         move.w    d5,ac_per(a0)        ;push period
  1977.         moveq    #0,d0
  1978.         move.b    trk_tempvol(a5),d0
  1979.         bpl.s    plr_upv_setvol
  1980.         move.b    trk_prevvol(a5),d0
  1981. plr_upv_setvol    st    trk_tempvol(a5)
  1982. ; -------- GetRelVol: Calculate track volume -----------------------------
  1983. ; track # = d7, note vol = d0, song = a4
  1984.     IFNE    RELVOL
  1985.         mulu    trk_trackvol(a5),d0    ;d0 = master v. * track v. * volume
  1986.         lsr.w    #8,d0
  1987.     ENDC
  1988.         move.w    d0,ac_vol(a0)
  1989.         rts
  1990.  
  1991. ; **** a separate routine for handling command 0F
  1992. fx_0f        cmp.b    #$f1,d4
  1993.         bne.s    no0ff1
  1994.         cmp.b    #3,d3
  1995.         beq.s    playfxnote
  1996.         rts
  1997. no0ff1:        cmp.b    #$f2,d4
  1998.         bne.s    no0ff2
  1999.         cmp.b    #3,d3
  2000.         beq.s    playfxnote
  2001.         rts
  2002. no0ff2:        cmp.b    #$f3,d4
  2003.         bne.s    no0ff3
  2004.         move.b    d3,d0
  2005.         beq.s    cF_rts
  2006.         and.b    #1,d0        ;is 2 or 4
  2007.         bne.s    cF_rts
  2008. playfxnote:    moveq    #0,d1
  2009.         move.b    trk_currnote(a5),d1    ;get note # of curr. note
  2010.         beq.s    cF_rts
  2011.         move.b    trk_noteoffcnt(a5),d0    ;get hold counter
  2012.         bmi.s    pfxn_nohold        ;no hold, or hold over
  2013.         add.b    d3,d0            ;increase by counter val
  2014.         bra.s    pfxn_hold
  2015. pfxn_nohold    move.b    trk_inithold(a5),d0    ;get initial hold
  2016.         bne.s    pfxn_hold
  2017.         st    d0
  2018. pfxn_hold    move.b    d0,trk_noteoffcnt(a5)
  2019.         movem.l    a1/a3/d3/d6,-(sp)
  2020.         moveq    #0,d3
  2021.         move.b    trk_previnstr(a5),d3    ;and prev. sample #
  2022.         movea.l    trk_previnstra(a5),a3
  2023.         bsr    _PlayNote
  2024. pndone_0ff    movem.l    (sp)+,a1/a3/d3/d6
  2025. cF_rts        rts
  2026. no0ff3:        cmp.b    #$f4,d4        ;triplet cmd 1
  2027.         bne.s    no0ff4
  2028.         moveq    #0,d0
  2029.         move.b    msng_tempo2(a4),d0
  2030.         divu    #3,d0
  2031.         cmp.b    d0,d3
  2032.         beq.s    playfxnote
  2033.         rts
  2034. no0ff4        cmp.b    #$f5,d4        ;triplet cmd 2
  2035.         bne.s    no0ff5
  2036.         moveq    #0,d0
  2037.         move.b    msng_tempo2(a4),d0
  2038.         divu    #3,d0
  2039.         add.w    d0,d0
  2040.         cmp.b    d0,d3
  2041.         beq.s    playfxnote
  2042.         rts
  2043. no0ff5        cmp.b    #$f7,d4
  2044.         bne.s    no0ff7
  2045.     IFNE    MIDI
  2046.         tst.b    d3
  2047.         bne.s    1$
  2048.         tst.b    sysx-DB(a6)
  2049.         beq.s    1$
  2050.         addq.w    #1,blkdelay-DB(a6)
  2051.     ENDC
  2052. 1$        rts
  2053. no0ff7        cmp.b    #$f8,d4        ;f8 = filter off
  2054.         beq.s    plr_filteroff
  2055.         cmp.b    #$f9,d4        ;f9 = filter on
  2056.         bne.s    cF_rts
  2057.         bclr    #1,$bfe001
  2058.         bset    #0,msng_flags(a4)
  2059.         rts
  2060. plr_filteroff:    bset    #1,$bfe001
  2061.         bclr    #0,msng_flags(a4)
  2062.         rts
  2063.  
  2064. ; -------- HANDLE DMA WAIT (PROCESSOR-INDEPENDENT) -----------------------
  2065. _Wait1line:    move.w    d0,-(sp)
  2066. wl0:        move.b    $dff007,d0
  2067. wl1:        cmp.b    $dff007,d0
  2068.         beq.s    wl1
  2069.         dbf    d1,wl0
  2070.         move.w    (sp)+,d0
  2071.         rts
  2072. pushnewvals:    movea.l    (a1)+,a5
  2073.         lsr.b    #1,d0
  2074.         bcc.s    rpnewv
  2075.         move.l    trk_sampleptr(a5),d1
  2076.         beq.s    rpnewv
  2077.         movea.l    trk_audioaddr(a5),a0
  2078.         move.l    d1,ac_ptr(a0)
  2079.         move.w    trk_samplelen(a5),ac_len(a0)
  2080. rpnewv:        rts
  2081.  
  2082. ; -------- AUDIO DMA ROUTINE ---------------------------------------------
  2083. _StartDMA:    ;This small routine turns on audio DMA
  2084.         move.w    dmaonmsk-DB(a6),d0    ;dmaonmsk contains the mask of
  2085.         beq.s    sdma_nodmaon    ;the channels that must be turned on
  2086.     IFNE    FASTMEMPLAY
  2087.         tst.w    _use_fastmem-DB(a6)
  2088.         beq.s    sdma_nofastmem
  2089.         bsr.s    sdma_fastmem
  2090.         bra.s    sdma_nodmaon
  2091.     ENDC
  2092. sdma_nofastmem    bset    #15,d0    ;DMAF_SETCLR: set these bits in dmacon
  2093.         moveq    #80,d1
  2094. ; The following line makes the playroutine one scanline slower. If your
  2095. ; song works well without the following instruction, you can leave it out.
  2096.     IFNE    SYNTH
  2097.         add.w    d1,d1    ;sometimes double wait time is required
  2098.     ENDC
  2099.         bsr.s    _Wait1line
  2100.         move.w    d0,$dff096    ;do that!!!
  2101.         moveq    #80,d1
  2102.         bsr.s    _Wait1line
  2103.         lea    trackdataptrs-DB(a6),a1
  2104.         bsr.s    pushnewvals
  2105.         bsr.s    pushnewvals
  2106.         bsr.s    pushnewvals
  2107.     IFNE    MIDI
  2108.         bsr.s    pushnewvals
  2109.     ENDC
  2110.     IFEQ    MIDI
  2111.         bra.s    pushnewvals
  2112.     ENDC
  2113. sdma_nodmaon
  2114.     IFNE    MIDI
  2115.         lea    bytesinnotebuff-DB(a6),a0
  2116.         move.w    (a0)+,d0
  2117.         beq.s    rpnewv
  2118.         bra.w    _AddMIDId
  2119.     ENDC
  2120. sdma_rts    rts
  2121.     IFNE    FASTMEMPLAY
  2122. sdma_fastmem    move.w    intonmsk-DB(a6),d0
  2123.         beq.s    sdma_rts
  2124.         movem.l    a2/a5/d2,-(sp)
  2125.         move.w    d0,d2
  2126.         lea    trackdataptrs-DB(a6),a2
  2127.         movea.l    (a2)+,a1
  2128.         lsr.w    #8,d2
  2129.         bcc.s    1$
  2130.         movea.l    trk_fmp(a1),a1
  2131.         lea    $DFF000,a0
  2132.         bsr.w    _FmpIntHandler
  2133. 1$        movea.l    (a2)+,a1
  2134.         lsr.b    #1,d2
  2135.         bcc.s    2$
  2136.         movea.l    trk_fmp(a1),a1
  2137.         lea    $DFF000,a0
  2138.         bsr.w    _FmpIntHandler
  2139. 2$        movea.l    (a2)+,a1
  2140.         lsr.b    #1,d2
  2141.         bcc.s    3$
  2142.         movea.l    trk_fmp(a1),a1
  2143.         lea    $DFF000,a0
  2144.         bsr.w    _FmpIntHandler
  2145. 3$        lsr.b    #1,d2
  2146.         bcc.s    4$
  2147.         movea.l    (a2),a1
  2148.         movea.l    trk_fmp(a1),a1
  2149.         lea    $DFF000,a0
  2150.         bsr.w    _FmpIntHandler
  2151. 4$        movem.l    (sp)+,a2/a5/d2
  2152.         moveq    #80,d1
  2153.         bsr    _Wait1line
  2154.         move.w    intonmsk-DB(a6),d1
  2155.         move.w    d1,INTREQ
  2156.         move.w    dmaonmsk-DB(a6),d0
  2157.         bset    #15,d0
  2158.         move.w    d0,DMACON    ;turn on DMA
  2159.         move.w    intonmsk-DB(a6),d1
  2160.         bset    #15,d1
  2161.         move.w    d1,INTENA    ;enable interrupts
  2162.         moveq    #80,d1
  2163.         bra    _Wait1line
  2164.     ENDC
  2165.  
  2166. _SetTempo:
  2167.     IFNE    CIAB
  2168.         move.l    _module-DB(a6),d1
  2169.         beq.s    ST_x
  2170.         move.l    d1,a0
  2171.         movea.l    mmd_songinfo(a0),a0
  2172.         move.w    d0,msng_deftempo(a0)
  2173.         btst    #5,msng_flags2(a0)
  2174.         bne.s    ST_bpm
  2175.         cmp.w    #10,d0    ;If tempo <= 10, use SoundTracker tempo
  2176.         bhi.s    calctempo
  2177.         subq.b    #1,d0
  2178.         add.w    d0,d0
  2179.         move.w    sttempo+2(pc,d0.w),d1
  2180.         bra.s    pushtempo
  2181. calctempo:    move.l    timerdiv-DB(a6),d1
  2182.         divu    d0,d1
  2183. pushtempo:    movea.l    craddr+4-DB(a6),a0
  2184.         move.b    d1,(a0)        ;and set the CIA timer
  2185.         lsr.w    #8,d1
  2186.         movea.l    craddr+8-DB(a6),a0
  2187.         move.b    d1,(a0)
  2188.     ENDC
  2189. ST_x        rts ;   vv-- These values are the SoundTracker tempos (approx.)
  2190. sttempo:    dc.w    $0f00
  2191.     IFNE    CIAB
  2192.         dc.w    2417,4833,7250,9666,12083,14500,16916,19332,21436,24163
  2193. ST_bpm        move.b    msng_flags2(a0),d1
  2194.         and.w    #$1F,d1
  2195.         addq.b    #1,d1
  2196.         mulu    d1,d0
  2197.         move.l    bpmdiv-DB(a6),d1
  2198.         divu    d0,d1
  2199.         bra.s    pushtempo
  2200.     ENDC
  2201.  
  2202.     IFNE    MIDI
  2203. MIDIFX        add.b    d0,d0    ;* 2
  2204.         move.w    midicmd_table(pc,d0.w),d0
  2205.         jmp    midifx(pc,d0.w)
  2206. midifx        
  2207. midicmd_table    dc.w    mfx_00-midifx,mfx_01-midifx,mfx_02-midifx,mfx_03-midifx,mfx_04-midifx
  2208.         dc.w    mfx_05-midifx,mfx_rts-midifx,mfx_rts-midifx,mfx_rts-midifx,mfx_rts-midifx
  2209.         dc.w    mfx_0a-midifx,mfx_rts-midifx,mfx_rts-midifx,mfx_0d-midifx,mfx_0e-midifx
  2210.         dc.w    mfx_0f-midifx
  2211.         dc.w    mfx_10-midifx,mfx_rts-midifx,mfx_rts-midifx,mfx_13-midifx
  2212.         dc.w    mfx_rts-midifx,mfx_rts-midifx,mfx_rts-midifx,mfx_17-midifx
  2213.         dc.w    mfx_rts-midifx,mfx_rts-midifx,mfx_rts-midifx,mfx_rts-midifx
  2214.         dc.w    mfx_rts-midifx,mfx_rts-midifx,mfx_rts-midifx,fx_1f-midifx
  2215.         dc.w    mfx_rts-midifx,mfx_rts-midifx,mfx_rts-midifx,mfx_rts-midifx,mfx_rts-midifx,mfx_rts-midifx,mfx_rts-midifx,mfx_rts-midifx
  2216.         dc.w    mfx_rts-midifx,mfx_rts-midifx,mfx_rts-midifx,mfx_rts-midifx,mfx_rts-midifx,mfx_rts-midifx,mfx_rts-midifx,mfx_rts-midifx
  2217.         dc.w    mfx_rts-midifx,mfx_31-midifx,mfx_32-midifx,mfx_33-midifx,mfx_34-midifx,mfx_35-midifx,mfx_36-midifx,mfx_37-midifx
  2218.         dc.w    mfx_38-midifx,mfx_39-midifx,mfx_3A-midifx,mfx_3B-midifx,mfx_3C-midifx,mfx_3D-midifx,mfx_3E-midifx,mfx_3F-midifx
  2219.  
  2220. mfx_01        lea    prevmidipbend-DB(a6),a0
  2221.         moveq    #0,d1
  2222.         move.b    trk_prevmidich(a5),d1    ;get previous midi channel
  2223.         add.b    d1,d1        ;UWORD index
  2224.         tst.b    d4        ;x100??
  2225.         beq.s    resetpbend
  2226.         move.w    0(a0,d1.w),d0    ;get previous pitch bend
  2227.         lsl.w    #3,d4        ;multiply bend value by 8
  2228.         add.w    d4,d0
  2229.         cmp.w    #$3fff,d0
  2230.         bls.s    bendpitch
  2231.         move.w    #$3fff,d0
  2232. bendpitch:    move.w    d0,0(a0,d1.w)    ;save current pitch bend
  2233.         lsr.b    #1,d1        ;back to UBYTE
  2234.         or.b    #$e0,d1
  2235.         lea    noteondata-DB(a6),a0
  2236.         move.b    d1,(a0)        ;midi command & channel
  2237.         move.b    d0,1(a0)    ;lower value
  2238.         and.b    #$7f,1(a0)    ;clear bit 7
  2239.         lsr.w    #7,d0
  2240.         and.b    #$7f,d0        ;clr bit 7
  2241.         move.b    d0,2(a0)    ;higher 7 bits
  2242.         moveq    #3,d0
  2243.         bra.w    _AddMIDId
  2244.  
  2245. mfx_02        lea    prevmidipbend-DB(a6),a0
  2246.         moveq    #0,d1
  2247.         move.b    trk_prevmidich(a5),d1
  2248.         add.b    d1,d1
  2249.         tst.b    d4
  2250.         beq.s    resetpbend    ;x200??
  2251.         move.w    0(a0,d1.w),d0
  2252.         lsl.w    #3,d4
  2253.         sub.w    d4,d0
  2254.         bpl.s    bendpitch    ;not under 0
  2255.         moveq    #0,d0
  2256.         bra.s    bendpitch
  2257. resetpbend:    tst.b    d3        ;d3 = counter (remember??)
  2258.         bne.s    mfx_rts
  2259.         move.w    #$2000,d0
  2260.         bra.s    bendpitch
  2261. mfx_rts        rts
  2262. mfx_13
  2263. mfx_03        tst.b    d3
  2264.         bne.s    mfx_rts
  2265.         lea    prevmidipbend-DB(a6),a0
  2266.         moveq    #0,d1
  2267.         move.b    trk_prevmidich(a5),d1
  2268.         add.b    d1,d1
  2269.         move.b    d4,d0
  2270.         add.b    #128,d0
  2271.         lsl.w    #6,d0
  2272.         bra.s    bendpitch
  2273.  
  2274. mfx_0d        tst.b    d3
  2275.         bne.s    mfx_rts
  2276.         lea    noteondata+1-DB(a6),a0    ;CHANNEL AFTERTOUCH
  2277.         move.b    d4,(a0)    ;value
  2278.         bmi.s    mfx_rts
  2279.         move.b    trk_prevmidich(a5),-(a0)
  2280.         or.b    #$d0,(a0)
  2281.         moveq    #2,d0
  2282.         bra.w    _AddMIDId
  2283.  
  2284. mfx_0a        tst.b    d3
  2285.         bne.s    mfx_rts
  2286.         lea    noteondata+2-DB(a6),a0    ;POLYPHONIC AFTERTOUCH
  2287.         and.b    #$7f,d4
  2288.         move.b    d4,(a0)
  2289.         move.b    trk_prevmidin(a5),-(a0)
  2290.         ble.s    mfx_rts
  2291.         move.b    trk_prevmidich(a5),-(a0)
  2292.         or.b    #$A0,(a0)
  2293.         moveq    #3,d0
  2294.         bra.w    _AddMIDId
  2295.  
  2296. mfx_17        moveq    #$07,d0        ;07 = VOLUME
  2297.         bra.s    pushctrldata
  2298.  
  2299. mfx_04        moveq    #$01,d0        ;01 = MODULATION WHEEL
  2300.         bra.s    pushctrldata
  2301.  
  2302. mfx_0e        moveq    #$0a,d0
  2303. pushctrldata    tst.b    d3        ;do it only once in a note
  2304.         bne.s    mfx_rts2    ;(when counter = 0)
  2305. pushctrld_nochk
  2306.         lea    noteondata+2-DB(a6),a0 ;push "control change" data,
  2307.         move.b    d4,(a0)        ;second databyte
  2308.         bmi.s    mfx_rts2    ;$0 - $7F only
  2309.         move.b    d0,-(a0)    ;1st databyte
  2310.         move.b    trk_prevmidich(a5),-(a0)    ;MIDI channel
  2311.         or.b    #$b0,(a0)    ;command (B)
  2312.         moveq    #3,d0
  2313.         bra.w    _AddMIDId
  2314.  
  2315. mfx_05        and.b    #$7f,d4        ;set contr. value of curr. MIDI ch.
  2316.         move.b    trk_prevmidich(a5),d6
  2317.         lea    midicontrnum-DB(a6),a0
  2318.         adda.w    d6,a0
  2319.         move.b    d4,(a0)
  2320. mfx_rts2    rts
  2321.  
  2322. mfx_0f        cmp.b    #$fa,d4        ;hold pedal ON
  2323.         bne.s    nomffa
  2324.         moveq    #$40,d0
  2325.         moveq    #$7f,d4
  2326.         bra.s    pushctrldata
  2327. nomffa        cmp.b    #$fb,d4        ;hold pedal OFF
  2328.         bne.w    fx_0f
  2329.         moveq    #$40,d0
  2330.         moveq    #$00,d4
  2331.         bra.s    pushctrldata
  2332.  
  2333. mfx_00        tst.b    d4
  2334.         beq.s    mfx_rts2
  2335.         and.b    #$7f,d4
  2336.         move.b    trk_prevmidich(a5),d6
  2337.         lea    midicontrnum-DB(a6),a0
  2338.         move.b    0(a0,d6.w),d0
  2339.         bra.s    pushctrldata
  2340.  
  2341. mfx_10        tst.b    d3
  2342.         bne.s    1$
  2343.         move.w    d4,d0
  2344.         bra.w    _InitMIDIDump
  2345. 1$        rts
  2346.  
  2347. ; *** Command 3cxx handling
  2348.  
  2349. mfx_31        moveq    #0,d0
  2350.         bra.s    mfx_3x
  2351. mfx_32        moveq    #sizeof_mcs,d0
  2352.         bra.s    mfx_3x
  2353. mfx_33        moveq    #sizeof_mcs*2,d0
  2354.         bra.s    mfx_3x
  2355. mfx_34        moveq    #sizeof_mcs*3,d0
  2356.         bra.s    mfx_3x
  2357. mfx_35        moveq    #sizeof_mcs*4,d0
  2358.         bra.s    mfx_3x
  2359. mfx_36        moveq    #sizeof_mcs*5,d0
  2360.         bra.s    mfx_3x
  2361. mfx_37        moveq    #sizeof_mcs*6,d0
  2362.         bra.s    mfx_3x
  2363. mfx_38        moveq    #sizeof_mcs*7,d0
  2364.         bra.s    mfx_3x
  2365. mfx_39        moveq    #sizeof_mcs*8,d0
  2366.         bra.s    mfx_3x
  2367. mfx_3A        moveq    #sizeof_mcs*9,d0
  2368.         bra.s    mfx_3x
  2369. mfx_3B        moveq    #sizeof_mcs*10,d0
  2370.         bra.s    mfx_3x
  2371. mfx_3C        moveq    #sizeof_mcs*11,d0
  2372.         bra.s    mfx_3x
  2373. mfx_3D        moveq    #sizeof_mcs*12,d0
  2374.         bra.s    mfx_3x
  2375. mfx_3E        moveq    #sizeof_mcs*13,d0
  2376.         bra.s    mfx_3x
  2377. mfx_3F        moveq    #sizeof_mcs*14,d0
  2378. mfx_3x        tst.b    d3    ;counter?
  2379.         bne.w    mcs_notype5
  2380.         lea    cmd3xsettings-DB(a6),a0
  2381.         adda.w    d0,a0
  2382.         move.w    mcs_controller(a0),d1
  2383.         move.b    mcs_type(a0),d0
  2384.         bne.s    mcs_notype0
  2385. ; *** MCS type: STD (MSB)
  2386.         cmp.w    #$7F,d1
  2387.         bhi.s    1$
  2388.         move.b    d1,d0
  2389.         bra    pushctrld_nochk
  2390. 1$        rts
  2391. mcs_notype0    subq.b    #1,d0
  2392.         bne.s    mcs_notype1
  2393. ; *** MCS type: STD (LSB)
  2394.         cmp.w    #$7F,d1
  2395.         bhi.s    1$
  2396.         cmp.w    #$1F,d1
  2397.         bhi.s    2$
  2398.         add.w    #$20,d1        ;if contr. num was 0 - 1F, add $20 to get contr. LSB
  2399. 2$        move.b    d1,d0
  2400.         bra    pushctrld_nochk
  2401. 1$        rts
  2402. mcs_notype1    subq.b    #1,d0
  2403.         bne.s    mcs_notype2
  2404. ; *** MCS type: RPN (MSB)
  2405.         move.l    d2,-(sp)
  2406.         move.w    d1,d2
  2407.         addq.w    #1,d2        ;ctrlr num + 1
  2408.         lea    noteondata-DB(a6),a0
  2409.         moveq    #0,d0
  2410.         move.b    trk_prevmidich(a5),d0
  2411.         lea    prevmidiptype-DB(a6),a1
  2412.         bclr    #0,0(a1,d0.w)    ;test last parameter: RPN or NRPN?, set RPN
  2413.         lea    prevmidipn-DB(a6),a1 ;load parameter address in A1
  2414.         adda.w    d0,a1
  2415.         adda.w    d0,a1
  2416.         bne.s    1$        ;NRPN... send full ident
  2417.         cmp.w    (a1),d2        ;the same parameter number?
  2418.         bne.s    1$        ;no.. send param. number
  2419.         or.b    #$B0,d0
  2420.         move.b    d0,(a0)+
  2421.         moveq    #3,d0
  2422.         bra.s    2$
  2423. 1$        move.w    d2,(a1)
  2424.         or.b    #$B0,d0
  2425.         move.b    d0,(a0)+
  2426.         move.b    #$64,(a0)+    ;RPN LSB
  2427.         move.b    d1,(a0)
  2428.         and.b    #$7F,(a0)+    ;lower 7 bits of ctrlr number
  2429.         lsr.w    #7,d1
  2430.         move.b    #$65,(a0)+    ;RPN MSB
  2431.         move.b    d1,(a0)+
  2432.         moveq    #7,d0
  2433. 2$        move.b    #$06,(a0)+    ;data entry, MSB
  2434.         move.b    d4,(a0)
  2435.         lea    noteondata-DB(a6),a0
  2436.         move.l    (sp)+,d2
  2437.         bra.w    _AddMIDId
  2438. mcs_notype2    subq.b    #1,d0
  2439.         bne.s    mcs_notype3
  2440. ; *** MCS type: RPN (LSB)
  2441.         move.l    d2,-(sp)
  2442.         move.w    d1,d2
  2443.         addq.w    #1,d2        ;ctrlr num + 1
  2444.         lea    noteondata-DB(a6),a0
  2445.         moveq    #0,d0
  2446.         move.b    trk_prevmidich(a5),d0
  2447.         lea    prevmidiptype-DB(a6),a1
  2448.         bclr    #0,0(a1,d0.w)    ;test last parameter: RPN or NRPN?, set RPN
  2449.         lea    prevmidipn-DB(a6),a1 ;load parameter address in A1
  2450.         adda.w    d0,a1
  2451.         adda.w    d0,a1
  2452.         bne.s    1$        ;NRPN... send full ident
  2453.         cmp.w    (a1),d2        ;the same parameter number?
  2454.         bne.s    1$        ;no.. send param. number
  2455.         or.b    #$B0,d0
  2456.         move.b    d0,(a0)+
  2457.         moveq    #3,d0
  2458.         bra.s    2$
  2459. 1$        move.w    d2,(a1)
  2460.         or.b    #$B0,d0
  2461.         move.b    d0,(a0)+
  2462.         move.b    #$64,(a0)+    ;RPN LSB
  2463.         move.b    d1,(a0)
  2464.         and.b    #$7F,(a0)+    ;lower 7 bits of ctrlr number
  2465.         lsr.w    #7,d1
  2466.         move.b    #$65,(a0)+    ;RPN MSB
  2467.         move.b    d1,(a0)+
  2468.         moveq    #7,d0
  2469. 2$        move.b    #$26,(a0)+    ;data entry, LSB
  2470.         move.b    d4,(a0)
  2471.         lea    noteondata-DB(a6),a0
  2472.         move.l    (sp)+,d2
  2473.         bra.w    _AddMIDId
  2474. mcs_notype3    subq.b    #1,d0
  2475.         bne.s    mcs_notype4
  2476. ; *** MCS type: NRPN (MSB)
  2477.         move.l    d2,-(sp)
  2478.         move.w    d1,d2
  2479.         addq.w    #1,d2        ;ctrlr num + 1
  2480.         lea    noteondata-DB(a6),a0
  2481.         moveq    #0,d0
  2482.         move.b    trk_prevmidich(a5),d0
  2483.         lea    prevmidiptype-DB(a6),a1
  2484.         bset    #0,0(a1,d0.w)    ;test last parameter: RPN or NRPN?, set NRPN
  2485.         lea    prevmidipn-DB(a6),a1 ;load parameter address in A1
  2486.         adda.w    d0,a1
  2487.         adda.w    d0,a1
  2488.         beq.s    1$        ;RPN... send full ident
  2489.         cmp.w    (a1),d2        ;the same parameter number?
  2490.         bne.s    1$        ;no.. send param. number
  2491.         or.b    #$B0,d0
  2492.         move.b    d0,(a0)+
  2493.         moveq    #3,d0
  2494.         bra.s    2$
  2495. 1$        move.w    d2,(a1)
  2496.         or.b    #$B0,d0
  2497.         move.b    d0,(a0)+
  2498.         move.b    #$62,(a0)+    ;NRPN LSB
  2499.         move.b    d1,(a0)
  2500.         and.b    #$7F,(a0)+    ;lower 7 bits of ctrlr number
  2501.         lsr.w    #7,d1
  2502.         move.b    #$63,(a0)+    ;NRPN MSB
  2503.         move.b    d1,(a0)+
  2504.         moveq    #7,d0
  2505. 2$        move.b    #$06,(a0)+    ;data entry, MSB
  2506.         move.b    d4,(a0)
  2507.         lea    noteondata-DB(a6),a0
  2508.         move.l    (sp)+,d2
  2509.         bra.w    _AddMIDId
  2510. mcs_notype4    subq.b    #1,d0
  2511.         bne.s    mcs_notype5
  2512. ; *** MCS type: NRPN (MSB)
  2513.         move.l    d2,-(sp)
  2514.         move.w    d1,d2
  2515.         addq.w    #1,d2        ;ctrlr num + 1
  2516.         lea    noteondata-DB(a6),a0
  2517.         moveq    #0,d0
  2518.         move.b    trk_prevmidich(a5),d0
  2519.         lea    prevmidiptype-DB(a6),a1
  2520.         bset    #0,0(a1,d0.w)    ;test last parameter: RPN or NRPN?, set NRPN
  2521.         lea    prevmidipn-DB(a6),a1 ;load parameter address in A1
  2522.         adda.w    d0,a1
  2523.         adda.w    d0,a1
  2524.         beq.s    1$        ;RPN... send full ident
  2525.         cmp.w    (a1),d2        ;the same parameter number?
  2526.         bne.s    1$        ;no.. send param. number
  2527.         or.b    #$B0,d0
  2528.         move.b    d0,(a0)+
  2529.         moveq    #3,d0
  2530.         bra.s    2$
  2531. 1$        move.w    d2,(a1)
  2532.         or.b    #$B0,d0
  2533.         move.b    d0,(a0)+
  2534.         move.b    #$62,(a0)+    ;NRPN LSB
  2535.         move.b    d1,(a0)
  2536.         and.b    #$7F,(a0)+    ;lower 7 bits of ctrlr number
  2537.         lsr.w    #7,d1
  2538.         move.b    #$63,(a0)+    ;NRPN MSB
  2539.         move.b    d1,(a0)+
  2540.         moveq    #7,d0
  2541. 2$        move.b    #$26,(a0)+    ;data entry, MSB
  2542.         move.b    d4,(a0)
  2543.         lea    noteondata-DB(a6),a0
  2544.         move.l    (sp)+,d2
  2545.         bra.w    _AddMIDId
  2546. mcs_notype5    rts
  2547.  
  2548.  
  2549. _ResetMIDI:    movem.l    d2/a2/a6,-(sp)
  2550.         movea.l    4.w,a6        ;ExecBase
  2551.         jsr    -$78(a6)    ;Disable()
  2552.         lea    DB,a6
  2553. ; Clear preset memory
  2554.         lea    prevmidicpres-DB(a6),a0
  2555.         moveq    #7,d2
  2556. RM_loop0    clr.l    (a0)+    ;force presets to be set again
  2557.         dbf    d2,RM_loop0
  2558.         clr.b    lastcmdbyte
  2559. ; Reset pitchbenders & modulation wheels
  2560.         lea    midiresd-DB(a6),a2
  2561.         move.b    #$e0,(a2)
  2562.         move.b    #$b0,3(a2)
  2563.         moveq    #15,d2
  2564. respbendl:    movea.l    a2,a0
  2565.         moveq    #6,d0
  2566.         bsr.w    _AddMIDId
  2567.         addq.b    #1,(a2)
  2568.         addq.b    #1,3(a2)
  2569.         dbf    d2,respbendl
  2570.         lea    prevmidipbend-DB(a6),a2
  2571.         moveq    #15,d2
  2572. 1$        move.w    #$2000,(a2)+
  2573.         dbf    d2,1$
  2574. ; Clear parameters (set to undefined)
  2575.         lea    prevmidipn-DB(a6),a2
  2576.         lea    prevmidiptype-DB(a6),a0
  2577.         moveq    #15,d2
  2578. 2$        clr.w    (a2)+
  2579.         clr.b    (a0)+
  2580.         dbf    d2,2$
  2581. ; Clear dump variables
  2582.         clr.b    sysx-DB(a6)
  2583.         lea    dumpqueue-DB(a6),a0
  2584.         move.l    a0,dqreadptr-DB(a6)
  2585.         move.l    a0,dqwriteptr-DB(a6)
  2586.         clr.w    dqentries-DB(a6)
  2587. ; Enable & exit
  2588.         movea.l    4.w,a6
  2589.         jsr    -$7e(a6)    ;Enable()
  2590.         movem.l    (sp)+,d2/a2/a6
  2591.         rts
  2592.     ENDC
  2593.  
  2594.     IFNE    FASTMEMPLAY
  2595. ;FastMemPlay interrupt handler routine
  2596. ;NOTE: audio buffer length must be divisible by 4!
  2597. _FmpIntHandler
  2598.         move.w    fmp_intmask(a1),$9C(a0)
  2599. ; --- See which buffer is in turn
  2600.         not.b    fmp_whichbuff(a1)
  2601.         beq.s    fih_fillbuff
  2602.         movea.l    fmp_bufferptr2(a1),a5
  2603.         bra.s    fih_fb2
  2604. fih_fillbuff    movea.l    fmp_bufferptr(a1),a5
  2605. ; --- Set the audio address for the next buffer
  2606. fih_fb2        movea.l    fmp_audioaddr(a1),a0
  2607.         move.l    a5,ac_ptr(a0)    ;new sample pointer
  2608. ; --- Check whether the channel has something valid to play
  2609.         tst.b    fmp_active(a1)
  2610.         beq.s    fih_inactive
  2611. ; --- Load remaining buffer size and sample pointer
  2612.         moveq    #0,d1
  2613.         move.w    fmp_buffsize(a1),d1
  2614.         move.l    fmp_currlen(a1),d0
  2615.         movea.l    fmp_currptr(a1),a0
  2616. ; --- If the remaining sample data entirely fills the buffer,
  2617. ; --- do a longword copy
  2618.         cmp.l    d1,d0
  2619.         bhi.s    fih_fill_whole_l
  2620. ; --- Loop. Subtract the remaining sample sz from rem. buffer sz
  2621. fih_loop1    sub.w    d0,d1
  2622. ; --- Copy the remaining bytes of the sample
  2623.         bra.s    2$
  2624. 1$        move.b    (a0)+,(a5)+
  2625. 2$        dbra    d0,1$
  2626. ; --- If no repeat, go and clear the rest of the buffer
  2627.         move.l    fmp_repeatptr(a1),d0
  2628.         beq.s    fih_norpt
  2629. ; --- Load repeat begin pointer to A0
  2630.         move.l    d0,a0
  2631. ; --- And length in D0
  2632.         move.l    fmp_repeatlen(a1),d0
  2633. ; --- If buffer was exactly filled, exit
  2634.         tst.w    d1
  2635.         beq.s    fih_exitintr
  2636. ; --- See whether the buffer could be now filled to the end
  2637. ; --- (can't use longword copy, because the destination might not be
  2638. ; --- aligned due to odd loop length)
  2639.         cmp.l    d1,d0
  2640.         bhi.s    fih_fill_whole
  2641.         bra.s    fih_loop1
  2642. fih_exitintr    move.l    d0,fmp_currlen(a1)
  2643.         move.l    a0,fmp_currptr(a1)
  2644.         rts
  2645.  
  2646. fih_fill_whole_l
  2647. ; --- Subtract copied bytes in advance
  2648.         sub.l    d1,d0
  2649. ; --- Store the remaining sample length
  2650.         move.l    d0,fmp_currlen(a1)
  2651.         move.l    a0,d0
  2652. ; --- Make sure the source is really aligned (it might not be, if the
  2653. ; --- loop was aligned on an even boundary)
  2654.         btst    #0,d0
  2655.         bne.s    fih_fill_nonalign
  2656. ; --- # of longwords
  2657.         lsr.w    #2,d1
  2658.         subq.w    #1,d1
  2659. 1$        move.l    (a0)+,(a5)+
  2660.         dbra    d1,1$
  2661. ; --- Also store the new source pointer, and exit..
  2662.         move.l    a0,fmp_currptr(a1)
  2663.         rts
  2664. ; --- The same as above, but not a longword copy.
  2665. fih_fill_whole    sub.l    d1,d0
  2666.         move.l    d0,fmp_currlen(a1)
  2667. fih_fill_nonalign
  2668.         subq.w    #1,d1
  2669. 1$        move.b    (a0)+,(a5)+
  2670.         dbra    d1,1$
  2671.         move.l    a0,fmp_currptr(a1)
  2672.         rts
  2673.  
  2674. ; --- Turn off this interrupt, and Audio DMA
  2675. fih_inactive    move.w    fmp_intmask(a1),d0
  2676.         move.w    d0,INTENA
  2677.         lsr.w    #7,d0
  2678.         move.w    d0,DMACON
  2679.         rts
  2680. ; --- Fill the rest of the buffer, and cause the channel to go
  2681. ; --- inactive when the interrupt occurs the next time
  2682. fih_clrloop    clr.b    (a5)+
  2683. fih_norpt    dbra    d1,fih_clrloop
  2684.         clr.b    fmp_active(a1)
  2685.         rts
  2686.  
  2687.  
  2688. _InitFastMemPlayer
  2689.         movem.l    a5/a6,-(sp)
  2690.         lea    DB,a5
  2691.         movea.l    _module-DB(a5),a0
  2692.         movea.l    mmd_songinfo(a0),a0
  2693.         tst.b    msng_flags2(a0)
  2694.         bmi.w    ifmp_noaudio    ;mixing! don't mess with audio hw..
  2695.         lea    fmpstructs,a0
  2696.         lea    $DFF0A0,a1
  2697.         move.w    _fmp_buffsize-DB(a5),d0
  2698.         move.w    d0,d1
  2699.         lsr.w    #1,d1
  2700.         move.w    #1<<7,fmp_intmask(a0)
  2701.         clr.w    fmp_whichbuff(a0)
  2702.         move.l    a1,fmp_audioaddr(a0)
  2703.         move.l    #_audiobuff,fmp_bufferptr(a0)
  2704.         move.l    #_audiobuff+800,fmp_bufferptr2(a0)
  2705.         move.w    d0,fmp_buffsize(a0)
  2706.         move.w    d1,ac_len(a1)
  2707.         lea    fmp_sizeof(a0),a0
  2708.         lea    $10(a1),a1
  2709.         move.w    #1<<8,fmp_intmask(a0)
  2710.         clr.w    fmp_whichbuff(a0)
  2711.         move.l    a1,fmp_audioaddr(a0)
  2712.         move.l    #_audiobuff+1600,fmp_bufferptr(a0)
  2713.         move.l    #_audiobuff+2400,fmp_bufferptr2(a0)
  2714.         move.w    d0,fmp_buffsize(a0)
  2715.         move.w    d1,ac_len(a1)
  2716.         lea    fmp_sizeof(a0),a0
  2717.         lea    $10(a1),a1
  2718.         move.w    #1<<9,fmp_intmask(a0)
  2719.         clr.w    fmp_whichbuff(a0)
  2720.         move.l    a1,fmp_audioaddr(a0)
  2721.         move.l    #_audiobuff+3200,fmp_bufferptr(a0)
  2722.         move.l    #_audiobuff+4000,fmp_bufferptr2(a0)
  2723.         move.w    d0,fmp_buffsize(a0)
  2724.         move.w    d1,ac_len(a1)
  2725.         lea    fmp_sizeof(a0),a0
  2726.         lea    $10(a1),a1
  2727.         move.w    #1<<10,fmp_intmask(a0)
  2728.         clr.w    fmp_whichbuff(a0)
  2729.         move.l    a1,fmp_audioaddr(a0)
  2730.         move.l    #_audiobuff+4800,fmp_bufferptr(a0)
  2731.         move.l    #_audiobuff+5600,fmp_bufferptr2(a0)
  2732.         move.w    d0,fmp_buffsize(a0)
  2733.         move.w    d1,ac_len(a1)
  2734.         movea.l    4.w,a6
  2735.         lea    fmpinterrupt0-DB(a5),a1
  2736.         moveq    #7,d0
  2737.         jsr    -$a2(a6)    ;SetIntVector()
  2738.         lea    fmpinterrupt1-DB(a5),a1
  2739.         moveq    #8,d0
  2740.         jsr    -$a2(a6)    ;SetIntVector()
  2741.         lea    fmpinterrupt2-DB(a5),a1
  2742.         moveq    #9,d0
  2743.         jsr    -$a2(a6)    ;SetIntVector()
  2744.         lea    fmpinterrupt3-DB(a5),a1
  2745.         moveq    #10,d0
  2746.         jsr    -$a2(a6)    ;SetIntVector()
  2747.         moveq    #1,d0
  2748.         move.w    d0,_use_fastmem-DB(a5)
  2749. ifmp_noaudio    movem.l    (sp)+,a5/a6
  2750.         rts
  2751.  
  2752. _RemAudioInts:    move.l    a6,-(sp)
  2753.         move.w    #$780,INTENA    ;switch audio interrupts off
  2754.         movea.l    4.w,a6
  2755.         suba.l    a1,a1
  2756.         moveq    #7,d0
  2757.         jsr    -$a2(a6)    ;SetIntVector()
  2758.         suba.l    a1,a1
  2759.         moveq    #8,d0
  2760.         jsr    -$a2(a6)    ;SetIntVector()
  2761.         suba.l    a1,a1
  2762.         moveq    #9,d0
  2763.         jsr    -$a2(a6)    ;SetIntVector()
  2764.         suba.l    a1,a1
  2765.         moveq    #10,d0
  2766.         jsr    -$a2(a6)    ;SetIntVector()
  2767.         clr.w    _use_fastmem
  2768.         move.l    (sp)+,a6
  2769.         rts
  2770.     ENDC
  2771.  
  2772. ; *************************************************************************
  2773. ; *************************************************************************
  2774. ; ***********          P U B L I C   F U N C T I O N S          ***********
  2775. ; *************************************************************************
  2776. ; *************************************************************************
  2777.  
  2778.         XDEF    _InitModule,_PlayModule
  2779.         XDEF    _InitPlayer,_RemPlayer,_StopPlayer
  2780.         XDEF    _ContModule
  2781.  
  2782. ; *************************************************************************
  2783. ; InitModule(a0 = module) -- extract expansion data etc.. from V3.xx module
  2784. ; *************************************************************************
  2785.  
  2786. _InitModule:    movem.l    a2-a3/d2,-(sp)
  2787.         move.l    a0,-(sp)
  2788.         beq    IM_exit            ;0 => xit
  2789.     IFNE    RELVOL
  2790.         movea.l    mmd_songinfo(a0),a1    ;MMD0song
  2791.         move.b    msng_mastervol(a1),d0    ;d0 = mastervol
  2792.         ext.w    d0
  2793.         lea    trackdataptrs,a2
  2794.         cmp.b    #'2',3(a0)        ;MMD2?
  2795.         bcs.s    IM_mmd01
  2796.         move.w    msng_numtracks(a1),d1
  2797.         subq.w    #1,d1
  2798.         movea.l    msng_trkvoltbl(a1),a1
  2799.         bra.s    IM_loop0
  2800. IM_mmd01    lea    msng_trkvol(a1),a1    ;a1 = trkvol
  2801.         moveq    #MAX_MMD1_TRACKS-1,d1
  2802. IM_loop0    move.b    (a1)+,d2    ;get vol...
  2803.         ext.w    d2
  2804.         move.l    (a2)+,a3    ;pointer to track data
  2805.         mulu    d0,d2        ;mastervol * trackvol
  2806.         lsr.w    #4,d2
  2807.         move.w    d2,trk_trackvol(a3)
  2808.         dbf    d1,IM_loop0
  2809.     ENDC
  2810.     IFNE    SYNTH
  2811.         lea    trackdataptrs,a2
  2812.         moveq    #3,d1
  2813. IM_loop1    move.l    (a2)+,a3
  2814.         clr.l    trk_synthptr(a3)
  2815.         clr.b    trk_synthtype(a3)
  2816.         dbf    d1,IM_loop1
  2817.     ENDC
  2818.         lea    holdvals,a2
  2819.         movea.l    a0,a3
  2820.         move.l    mmd_expdata(a0),d0    ;expdata...
  2821.         beq    IM_clrhlddec        ;none here
  2822.         move.l    d0,a1
  2823.         move.l    4(a1),d0        ;exp_smp
  2824.         beq    IM_clrhlddec    ;again.. nothing
  2825.         move.l    d0,a0        ;InstrExt...
  2826.         move.w    8(a1),d2    ;# of entries
  2827.         beq    IM_clrhlddec
  2828. ; perhaps >63 instruments are supported in the future... just in case...
  2829.         cmp.w    #63,d2
  2830.         ble.s    1$
  2831.         moveq    #63,d2
  2832. 1$        move.l    a4,-(sp)
  2833.         lea    rptrptlen,a4
  2834.         subq.w    #1,d2        ;-1 (for dbf)
  2835.         move.w    10(a1),d0    ;entry size
  2836.         movea.l    mmd_songinfo(a3),a3    ;MMD0song
  2837.     IFNE    MIDI
  2838.         lea    4*63(a2),a1    ;pointer to ext_midipsets...
  2839.     ENDC
  2840. IM_loop2    clr.b    2*63(a2)        ;clear finetune
  2841.         cmp.w    #3,d0
  2842.         ble.s    IM_noftune
  2843.         move.b    3(a0),126(a2)    ;InstrExt.finetune -> finetune
  2844. IM_noftune    clr.b    3*63(a2)    ;clear flags
  2845.         cmp.w    #6,d0
  2846.         blt.s    IM_noflags
  2847.         move.b    5(a0),3*63(a2)    ;InstrExt.flags -> flags
  2848.         bra.s    IM_gotflags
  2849. IM_noflags    cmp.w    #1,inst_replen(a3)
  2850.         bls.s    IM_gotflags
  2851.         bset    #0,3*63(a2)
  2852. IM_gotflags    clr.b    6*63(a2)    ;Initally OUTPUT_STD
  2853.         cmp.w    #9,d0
  2854.         blt.s    IM_noopdev
  2855.         move.b    8(a0),6*63(a2)    ;get InstrExt.output_device
  2856.     IFNE    AURA
  2857.         cmp.b    #1,8(a0)    ;is it OUTPUT_AURA?
  2858.         bne.s    IM_noopdev
  2859. ; does no harm to call several times...
  2860.         jsr    _InitAura(pc)
  2861.     ENDC
  2862. IM_noopdev    cmp.w    #18,d0
  2863.         blt.s    IM_nolongrpt
  2864.         move.l    10(a0),(a4)+    ;rpt
  2865.         move.l    14(a0),(a4)+    ;rptlen
  2866.         bra.s    IM_gotlongrpt
  2867. IM_nolongrpt    moveq    #0,d1
  2868.         move.w    inst_repeat(a3),d1
  2869.         add.l    d1,d1
  2870.         move.l    d1,(a4)+
  2871.         moveq    #0,d1
  2872.         move.w    inst_replen(a3),d1
  2873.         add.l    d1,d1
  2874.         move.l    d1,(a4)+
  2875. IM_gotlongrpt
  2876.     IFNE    MIDI
  2877.         cmp.w    #2,d0
  2878.         ble.s    IM_nsmnoff
  2879.         tst.b    2(a0)        ;suppress MIDI note off?
  2880.         beq.s    IM_nsmnoff
  2881.         bset    #7,inst_midich(a3)
  2882. IM_nsmnoff    move.b    inst_midipreset(a3),d1
  2883.         ext.w    d1
  2884.         move.w    d1,(a1)
  2885.         cmp.w    #8,d0
  2886.         ble.s    IM_nolongpset
  2887.         move.w    6(a0),(a1)    ;-> ext_midipsets
  2888.         btst    #1,5(a0)
  2889.         beq.s    IM_nolongpset
  2890.         bset    #6,inst_midich(a3)
  2891. IM_nolongpset    addq.l    #2,a1
  2892.     ENDC
  2893.         move.b    1(a0),63(a2)    ;InstrExt.decay -> decay
  2894.         move.b    (a0),(a2)+    ;InstrExt.hold -> holdvals
  2895.         adda.w    d0,a0        ;ptr to next InstrExt
  2896.         addq.l    #8,a3        ;next instrument...
  2897.         dbf    d2,IM_loop2
  2898.         move.l    (sp)+,a4
  2899.         bra.s    IM_exit
  2900. IM_clrhlddec    move.w    #3*63-1,d0    ;no InstrExt => clear holdvals/decays
  2901. IM_loop3    clr.w    (a2)+        ;..and finetunes/flags/ext_psets
  2902.         dbf    d0,IM_loop3
  2903.         movea.l    (sp),a0
  2904. ; -------- For (very old) MMDs, with no InstrExt, set flags/SSFLG_LOOP,
  2905. ; -------- also copy inst_midipreset to ext_midipsets.
  2906.         movea.l    mmd_songinfo(a0),a3
  2907.         lea    flags,a2
  2908.         lea    rptrptlen,a0
  2909.     IFNE    MIDI
  2910.         lea    ext_midipsets,a1
  2911.     ENDC
  2912.         moveq    #62,d0
  2913. IM_loop4    cmp.w    #1,inst_replen(a3)
  2914.         bls.s    IM_noreptflg
  2915.         bset    #0,(a2)
  2916. IM_noreptflg    addq.l    #1,a2
  2917.     IFNE    MIDI
  2918.         move.b    inst_midipreset(a3),d1
  2919.         ext.w    d1
  2920.         move.w    d1,(a1)+
  2921.     ENDC
  2922.         moveq    #0,d1
  2923.         move.w    inst_repeat(a3),d1
  2924.         add.l    d1,d1
  2925.         move.l    d1,(a0)+
  2926.         move.w    inst_replen(a3),d1
  2927.         add.l    d1,d1
  2928.         move.l    d1,(a0)+
  2929.         addq.l    #8,a3        ;next inst
  2930.         dbf    d0,IM_loop4
  2931. IM_exit
  2932. ; -------- Get MIDI command 3x settings (if they exist)
  2933.     IFNE    MIDI
  2934.         movea.l    (sp),a0
  2935.         lea    cmd3xsettings,a2
  2936.         move.l    mmd_expdata(a0),d0
  2937.         beq.s    IM_c3_clr
  2938.         move.l    d0,a0
  2939.         move.l    64(a0),d0    ;mmdcmd3x
  2940.         beq.s    IM_c3_clr
  2941.         move.l    d0,a0
  2942.         move.w    2(a0),d0    ;num_of_settings
  2943.         cmp.w    #15,d0
  2944.         bls.s    1$
  2945.         moveq    #15,d0
  2946. 1$        move.l    4(a0),d1    ;ctrlr types
  2947.         beq.s    IM_c3_clr
  2948.         movea.l    d1,a1
  2949.         move.l    8(a0),d1    ;ctrlr numbers
  2950.         beq.s    IM_c3_clr
  2951.         movea.l    d1,a3
  2952.         subq.w    #1,d0
  2953.         bmi.s    IM_c3_clr
  2954. 2$        move.b    (a1)+,d1
  2955.         ext.w    d1
  2956.         move.w    d1,(a2)+
  2957.         move.w    (a3)+,(a2)+
  2958.         dbra    d0,2$
  2959.         bra.s    IM_c3_exit
  2960. IM_c3_clr    moveq    #15-1,d0
  2961. 1$        clr.l    (a2)+
  2962.         dbra    d0,1$
  2963. IM_c3_exit
  2964.     ENDC
  2965. ; -------- Exit
  2966.         addq.l    #4,sp
  2967.         movem.l    (sp)+,a2-a3/d2
  2968.         rts
  2969. ; *************************************************************************
  2970. ; InitPlayer() -- allocate interrupt, audio, serial port etc...
  2971. ; *************************************************************************
  2972. _InitPlayer:
  2973.     IFNE    MIDI
  2974.         bsr.w    _GetSerial
  2975.         tst.l    d0
  2976.         bne.s    IP_error
  2977.     ENDC
  2978.         bsr.w    _AudioInit
  2979.         tst.l    d0
  2980.         bne.s    IP_error
  2981.         rts
  2982. IP_error    bsr.s    _RemPlayer
  2983.         moveq    #-1,d0
  2984.         rts
  2985. ; *************************************************************************
  2986. ; RemPlayer() -- free interrupt, audio, serial port etc..
  2987. ; *************************************************************************
  2988. _RemPlayer:    move.b    _timeropen,d0
  2989.         beq.s    RP_notimer    ;timer is not ours
  2990.         bsr.s    _StopPlayer
  2991. RP_notimer:    bsr.w    _AudioRem
  2992.     IFNE    MIDI
  2993.         bra.w    _FreeSerial
  2994.     ELSEIF
  2995.         rts
  2996.     ENDC
  2997. ; *************************************************************************
  2998. ; StopPlayer() -- stop the music
  2999. ; *************************************************************************
  3000. _StopPlayer:    lea    DB,a1
  3001.         move.b    _timeropen-DB(a1),d0
  3002.         beq.s    SP_end        ;res. alloc fail.
  3003.     IFNE    CIAB
  3004.         movea.l    craddr-DB(a1),a0
  3005.         bclr    #0,(a0)        ;stop timer
  3006.     ENDC
  3007.     IFNE    AURA
  3008.         jsr    _RemAura(pc)
  3009.     ENDC
  3010.     IFNE    FASTMEMPLAY
  3011.         bsr.w    _RemAudioInts
  3012.     ENDC
  3013.         lea    DB,a1
  3014.         move.l    _module-DB(a1),d0
  3015.         beq.s    SP_nomod
  3016.         move.l    d0,a0
  3017.         clr.w    mmd_pstate(a0)
  3018.         clr.l    _module-DB(a1)
  3019. SP_nomod
  3020.     IFNE    MIDI
  3021.         clr.b    lastcmdbyte-DB(a1)
  3022.     ENDC
  3023.         bra.w    SoundOff
  3024. SP_end        rts
  3025.  
  3026.  
  3027. _ContModule    tst.b    _timeropen
  3028.         beq.s    SP_end
  3029.         movea.l    craddr,a1
  3030.         bclr    #0,(a1)
  3031.         move.l    a0,-(sp)
  3032.         bsr.w    SoundOff
  3033.         move.l    (sp)+,a0
  3034.         moveq    #0,d0
  3035.         bra.s    contpoint
  3036. ; *************************************************************************
  3037. ; PlayModule(a0 = module)  -- initialize & play it!
  3038. ; *************************************************************************
  3039. _PlayModule:    st    d0
  3040. contpoint    movem.l    a0/d0,-(sp)
  3041.         bsr    _InitModule
  3042.         movem.l    (sp)+,a0/d0
  3043.         move.l    a6,-(sp)
  3044.         lea    DB,a6
  3045.         tst.b    _timeropen-DB(a6)
  3046.         beq    PM_end        ;resource allocation failure
  3047.         move.l    a0,d1
  3048.         beq    PM_end        ;module failure
  3049.     IFNE    CIAB
  3050.         movea.l    craddr-DB(a6),a1
  3051.         bclr    #0,(a1)        ;stop timer...
  3052.     ENDC
  3053.         clr.l    _module-DB(a6)
  3054.     IFNE    MIDI
  3055.         clr.b    lastcmdbyte-DB(a6)
  3056.     ENDC
  3057.         move.w    _modnum,d1
  3058.         beq.s    PM_modfound
  3059. PM_nextmod    tst.l    mmd_expdata(a0)
  3060.         beq.s    PM_modfound
  3061.         move.l    mmd_expdata(a0),a1
  3062.         tst.l    (a1)
  3063.         beq.s    PM_modfound        ;no more modules here!
  3064.         move.l    (a1),a0
  3065.         subq.w    #1,d1
  3066.         bgt.s    PM_nextmod
  3067. PM_modfound    cmp.b    #'T',3(a0)
  3068.         bne.s    PM_nomodT
  3069.         move.b    #'0',3(a0)    ;change MCNT to MCN0
  3070. PM_nomodT    movea.l    mmd_songinfo(a0),a1        ;song
  3071.         move.b    msng_tempo2(a1),mmd_counter(a0)    ;init counter
  3072.         tst.b    msng_flags2(a1)
  3073.         bmi.w    PM_end            ;requires mixing... FAIL!
  3074.         btst    #0,msng_flags(a1)
  3075.         bne.s    PM_filon
  3076.         bset    #1,$bfe001
  3077.         bra.s    PM_filset
  3078. PM_filon    bclr    #1,$bfe001
  3079. PM_filset    tst.b    d0
  3080.         beq.s    PM_noclr
  3081.         clr.l    mmd_pline(a0)
  3082.         clr.l    rptline-DB(a6)
  3083.         clr.w    blkdelay-DB(a6)
  3084. ; ---------- Set 'pblock' and 'pseq' to correct values...
  3085. PM_noclr    cmp.b    #'2',3(a0)
  3086.         bcs.s    PM_oldpbset
  3087.         move.w    mmd_psecnum(a0),d1
  3088.         move.l    a2,-(sp)        ;need extra register
  3089.         movea.l    msng_sections(a1),a2
  3090.         add.w    d1,d1
  3091.         move.w    0(a2,d1.w),d1        ;get sequence number
  3092.         add.w    d1,d1
  3093.         add.w    d1,d1
  3094.         move.w    d1,mmd_pseq(a0)
  3095.         movea.l    msng_pseqs(a1),a2
  3096.         movea.l    0(a2,d1.w),a2        ;PlaySeq...
  3097.         move.w    mmd_pseqnum(a0),d1
  3098.         add.w    d1,d1
  3099.         move.w    42(a2,d1.w),d1        ;and the correct block..
  3100.         move.l    (sp)+,a2
  3101.         bra.s    PM_setblk
  3102. PM_oldpbset    move.w    mmd_pseqnum(a0),d1
  3103.         add.w    #msng_playseq,d1
  3104.         move.b    0(a1,d1.w),d1        ;get first playseq entry
  3105.         ext.w    d1
  3106. PM_setblk    move.w    d1,mmd_pblock(a0)
  3107.         move.w    #-1,mmd_pstate(a0)
  3108.         move.l    a0,_module-DB(a6)
  3109.         btst    #5,msng_flags2(a1)    ;BPM?
  3110.         seq    bpmcounter-DB(a6)
  3111.     IFNE    FASTMEMPLAY
  3112.         tst.w    _fastmemplay-DB(a6)
  3113.         beq.s    PM_nofmp
  3114.         move.l    a1,-(sp)
  3115.         bsr.w    _InitFastMemPlayer
  3116.         movea.l    (sp)+,a1
  3117. PM_nofmp
  3118.     ENDC
  3119.     IFNE    CIAB
  3120.         move.w    msng_deftempo(a1),d0    ;get default tempo
  3121.         movea.l    craddr-DB(a6),a1
  3122.         bsr.w    _SetTempo    ;set default tempo
  3123.         bset    #0,(a1)        ;start timer => PLAY!!
  3124.     ENDC
  3125. PM_end        move.l    (sp)+,a6
  3126.         rts
  3127. ; *************************************************************************
  3128.  
  3129. _InitPlayRoutine
  3130.         lea    trackdataptrs,a0
  3131.         movea.l    (a0)+,a1
  3132.         move.l    #$dff0a0,trk_audioaddr(a1)
  3133.         move.l    #fmpstructs,trk_fmp(a1)
  3134.         movea.l    (a0)+,a1
  3135.         move.l    #$dff0b0,trk_audioaddr(a1)
  3136.         move.l    #fmpstructs+fmp_sizeof,trk_fmp(a1)
  3137.         movea.l    (a0)+,a1
  3138.         move.l    #$dff0c0,trk_audioaddr(a1)
  3139.         move.l    #fmpstructs+fmp_sizeof*2,trk_fmp(a1)
  3140.         movea.l    (a0),a1
  3141.         move.l    #$dff0d0,trk_audioaddr(a1)
  3142.         move.l    #fmpstructs+fmp_sizeof*3,trk_fmp(a1)
  3143.         lea    -12(a0),a0
  3144.         moveq    #3,d0
  3145. 2$        movea.l    (a0)+,a1
  3146.         st    trk_tempvol(a1)
  3147.         dbf    d0,2$
  3148.         rts
  3149.  
  3150. _AudioInit:    movem.l    a4/a6/d2-d3,-(sp)
  3151.         lea    DB,a4
  3152.         moveq    #0,d2
  3153.         movea.l    4.w,a6
  3154. ;    +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ alloc signal bit
  3155.     IFNE    AUDDEV
  3156.         moveq    #1,d2
  3157.         moveq    #-1,d0
  3158.         jsr    -$14a(a6)    ;AllocSignal()
  3159.         tst.b    d0
  3160.         bmi.w    initerr
  3161.         move.b    d0,sigbitnum-DB(a4)
  3162. ;    +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ prepare IORequest
  3163.         lea    allocport-DB(a4),a1
  3164.         move.b    d0,15(a1)    ;set mp_SigBit
  3165.         move.l    a1,-(sp)
  3166.         suba.l    a1,a1
  3167.         jsr    -$126(a6)    ;FindTask(0)
  3168.         move.l    (sp)+,a1
  3169.         move.l    d0,16(a1)    ;set mp_SigTask
  3170.         lea    reqlist-DB(a4),a0
  3171.         move.l    a0,(a0)        ;NEWLIST begins...
  3172.         addq.l    #4,(a0)
  3173.         clr.l    4(a0)
  3174.         move.l    a0,8(a0)    ;NEWLIST ends...
  3175. ;    +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ open audio.device
  3176.         moveq    #2,d2
  3177.         lea    allocreq-DB(a4),a1
  3178.         lea    audiodevname-DB(a4),a0
  3179.         moveq    #0,d0
  3180.         moveq    #0,d1
  3181.         movea.l    4.w,a6
  3182.         jsr    -$1bc(a6)    ;OpenDevice()
  3183.         tst.b    d0
  3184.         bne.w    initerr
  3185.         st    audiodevopen-DB(a4)
  3186. ;    +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ open cia resource
  3187.         moveq    #3,d2
  3188.     ENDC
  3189.     IFNE    CIAB
  3190.         cmp.b    #50,$212(a6)    ;ExecBase->VBlankFrequency
  3191.         beq.s    init_pal
  3192.         move.l    #474326,timerdiv-DB(a4) ;Assume that CIA freq is 715 909 Hz
  3193.         move.l    #3579545/2,bpmdiv-DB(a4)
  3194. init_pal    moveq    #0,d3
  3195.         lea    cianame-DB(a4),a1
  3196.         move.b    #'a',3(a1)
  3197. open_ciares    moveq    #0,d0
  3198.         movea.l    4.w,a6
  3199.         jsr    -$1f2(a6)    ;OpenResource()
  3200.         move.l    d0,_ciaresource
  3201.         beq.s    try_CIAB
  3202.         moveq    #4,d2
  3203.         move.l    d0,a6
  3204.         lea    timerinterrupt-DB(a4),a1
  3205.         moveq    #0,d0        ;Timer A
  3206.         jsr    -$6(a6)        ;AddICRVector()
  3207.         tst.l    d0
  3208.         beq.s    got_timer
  3209.         addq.l    #4,d3        ;add base addr index
  3210.         lea    timerinterrupt-DB(a4),a1
  3211.         moveq    #1,d0        ;Timer B
  3212.         jsr    -$6(a6)        ;AddICRVector()
  3213.         tst.l    d0
  3214.         beq.s    got_timer
  3215. try_CIAB    lea    cianame-DB(a4),a1
  3216.         cmp.b    #'a',3(a1)
  3217.         bne.s    initerr
  3218.         addq.b    #1,3(a1)
  3219.         moveq    #8,d3        ;CIAB base addr index = 8
  3220.         bra.w    open_ciares
  3221. ;    +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ attach interrupt
  3222. got_timer    lea    craddr+8-DB(a4),a6
  3223.         move.l    cia_addr(pc,d3.w),d0
  3224.         move.l    d0,(a6)
  3225.         sub.w    #$100,d0
  3226.         move.l    d0,-(a6)
  3227.         moveq    #2,d3        ;assume timer B
  3228.         btst    #9,d0        ;timer A or B ?
  3229.         bne.s    got_timerB
  3230.         subq.b    #1,d3        ;not timer B -> subtract 1
  3231.         add.w    #$100,d0    ;calc offset to timer control reg
  3232. got_timerB    add.w    #$900,d0
  3233.         move.l    d0,-(a6)
  3234.         move.l    d0,a0            ;get Control Register
  3235.         and.b    #%10000000,(a0)        ;clear CtrlReg bits 0 - 6
  3236.         move.b    d3,_timeropen-DB(a4)    ;d3: 1 = TimerA 2 = TimerB
  3237.     ENDC
  3238.     IFNE    VBLANK
  3239.         moveq    #5,d0        ;INTB_VERTB
  3240.         lea    timerinterrupt-DB(a4),a1
  3241.         jsr    -$a8(a6)    ;AddIntServer
  3242.         st    _timeropen-DB(a4)
  3243.     ENDC
  3244.     IFEQ    CIAB|VBLANK
  3245.         st    _timeropen-DB(a4)
  3246.     ENDC
  3247.         bsr.w    _InitPlayRoutine
  3248.         moveq    #0,d0
  3249. initret:    movem.l    (sp)+,a4/a6/d2-d3
  3250.         rts
  3251. initerr:    move.l    d2,d0
  3252.         bra.s    initret
  3253.  
  3254. cia_addr:    dc.l    $BFE501,$BFE701,$BFD500,$BFD700
  3255.  
  3256. _AudioRem:    movem.l    a5-a6,-(sp)
  3257.         lea    DB,a5
  3258.         moveq    #0,d0
  3259.         move.b    _timeropen,d0
  3260.         beq.s    rem1
  3261. ;    +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ remove interrupt
  3262.         clr.b    _timeropen
  3263.     IFNE    CIAB
  3264.         move.l    _ciaresource,a6
  3265.         lea    timerinterrupt-DB(a5),a1
  3266.         subq.b    #1,d0
  3267.         jsr    -$c(a6)        ;RemICRVector
  3268.     ENDC
  3269.     IFNE    VBLANK
  3270.         movea.l    4.w,a6
  3271.         lea    timerinterrupt(pc),a1
  3272.         moveq    #5,d0
  3273.         jsr    -$ae(a6)    ;RemIntServer
  3274.     ENDC
  3275. rem1:
  3276.     IFNE    AUDDEV
  3277.         movea.l    4.w,a6
  3278.         tst.b    audiodevopen-DB(a5)
  3279.         beq.s    rem2
  3280.         move.w    #$000f,$dff096    ;stop audio DMA
  3281. ;    +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ close audio.device
  3282.         lea    allocreq-DB(a5),a1
  3283.         jsr    -$1c2(a6)    ;CloseDevice()
  3284.         clr.b    audiodevopen-DB(a5)
  3285. rem2:        moveq    #0,d0
  3286.         move.b    sigbitnum-DB(a5),d0
  3287.         bmi.s    rem3
  3288. ;    +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ free signal bit
  3289.         jsr    -$150(a6)    ;FreeSignal()
  3290.         st    sigbitnum-DB(a5)
  3291. rem3:
  3292.     ENDC
  3293.         movem.l    (sp)+,a5-a6
  3294.         rts
  3295.  
  3296.     IFNE    MIDI
  3297. _GetSerial:    movem.l    a5-a6,-(sp)    ;Get serial port for MIDI
  3298.         lea    DB,a5
  3299.         bsr.s    GetSer2
  3300.         tst.l    d0        ;got the port??
  3301.         beq.s    rgser        ;yes
  3302.         movea.l    4.w,a6        ;no..try to flush serial.device:
  3303.         jsr    -$84(a6)        ;Forbid
  3304.         lea    $15e(a6),a0        ;ExecBase->DeviceList
  3305.         lea    serdev-DB(a5),a1    ;"serial.device"
  3306.         jsr    -$114(a6)        ;FindName
  3307.         tst.l    d0
  3308.         beq.s    serdnotf        ;no serial.device!!
  3309.         move.l    d0,a1
  3310.         jsr    -$1b6(a6)        ;RemDevice
  3311. serdnotf:    jsr    -$8a(a6)        ;and Permit
  3312.         bsr.s    GetSer2        ;now try it again...
  3313. rgser:        movem.l    (sp)+,a5-a6
  3314.         rts
  3315.  
  3316. GetSer2:    movea.l    4.w,a6
  3317.         moveq    #0,d0
  3318.         lea    miscresname-DB(a5),a1
  3319.         jsr    -$1f2(a6)    ;OpenResource()
  3320.         move.l    d0,miscresbase-DB(a5)
  3321.         tst.l    d0
  3322.         beq.s    gserror
  3323.         move.l    d0,a6
  3324.         lea    medname-DB(a5),a1
  3325.         moveq    #0,d0        ;serial port
  3326.         jsr    -$6(a6)        ;AllocMiscResource()
  3327.         tst.l    d0
  3328.         bne.s    gserror
  3329.         lea    medname-DB(a5),a1
  3330.         moveq    #1,d0        ;serial bits
  3331.         jsr    -$6(a6)
  3332.         tst.l    d0
  3333.         beq.s    gs2_allocok
  3334.         moveq    #0,d0
  3335.         jsr    -$c(a6)        ;bits failed -> Free serial port
  3336.         bra.s    gserror
  3337. gs2_allocok    move.w    $dff01c,d0
  3338.         btst    #0,d0
  3339.         sne    intrson-DB(a5)
  3340.         moveq    #0,d0        ;TBE
  3341.         lea    serinterrupt-DB(a5),a1
  3342.         move.l    4.w,a6
  3343.         jsr    -$a2(a6)    ;SetIntVector()
  3344.         move.l    d0,prevtbe-DB(a5)
  3345.         move.w    #$8001,$dff09a    ;TBE on
  3346.         move.w    #114,$dff032    ;set baud rate (SERPER)
  3347.         st    serportalloc-DB(a5)
  3348.         moveq    #0,d0
  3349.         rts
  3350. gserror:    moveq    #-1,d0
  3351.         rts
  3352.  
  3353. _FreeSerial:    movem.l    a5-a6,-(sp)
  3354.         lea    DB,a5
  3355.         tst.l    miscresbase-DB(a5)
  3356.         beq.s    retfs
  3357.         tst.b    serportalloc-DB(a5)
  3358.         beq.s    retfs
  3359. wmb_loop    move.w    $dff018,d0    ;WAIT until all data sent
  3360.         btst    #12,d0        ;test TSRE bit of SERDAT
  3361.         beq.s    wmb_loop
  3362.         move.w    #$0001,$dff09a    ;disable TBE
  3363.         movea.l    4.w,a6
  3364.         move.l    prevtbe-DB(a5),a1
  3365.         moveq    #0,d0
  3366.         jsr    -$a2(a6)    ;SetIntVector()
  3367. fs_noptbe    movea.l    miscresbase-DB(a5),a6
  3368.         moveq    #0,d0        ;serial port
  3369.         jsr    -$c(a6)        ;FreeMiscResource()
  3370.         moveq    #1,d0        ;serial bits
  3371.         jsr    -$c(a6)
  3372.         clr.b    serportalloc-DB(a5)
  3373.         clr.b    lastcmdbyte-DB(a5)
  3374. retfs:        movem.l    (sp)+,a5-a6
  3375.         rts
  3376.  
  3377. ; Message number in d0.
  3378. _InitMIDIDump:    tst.b    serportalloc
  3379.         beq.s    idd_rts
  3380.         movem.l    a1/a5/a6,-(sp)    ;a1 = data pointer, d1 = length
  3381.         lea    DB,a5
  3382.         movea.l    4.w,a6            ;ExecBase
  3383.         jsr    -$78(a6)        ;Disable()
  3384.         cmp.w    #16,dqentries-DB(a5)    ;dump queue full?
  3385.         bge.s    idd_exit        ;exit without doing anything
  3386.         lea    dqwriteptr-DB(a5),a1
  3387.         movea.l    (a1),a0
  3388.         move.w    d0,(a0)+        ;store message number
  3389.         cmpa.l    a1,a0            ;queue end?
  3390.         bne.s    idd_noresetbuff
  3391.         lea    dumpqueue-DB(a5),a0    ;reset write pointer
  3392. idd_noresetbuff    move.l    a0,(a1)            ;and write it back.
  3393.         addq.w    #1,dqentries-DB(a5)
  3394.         tst.b    sysx-DB(a5)        ;already sending data?
  3395.         bne.s    idd_exit        ;yes. Don't initiate new send.
  3396.         clr.b    lastcmdbyte-DB(a5)
  3397.         bsr    StartNewDump
  3398.         move.w    $dff018,d0        ;SERDATR
  3399.         btst    #13,d0
  3400.         beq.s    idd_exit
  3401.         move.w    #$8001,$dff09c        ;request TBE
  3402. idd_exit    jsr    -$7e(a6)        ;Enable()
  3403.         movem.l    (sp)+,a1/a5/a6
  3404. idd_rts        rts
  3405.  
  3406. SerIntHandler:    move.w    #$4000,$9a(a0)    ;disable..(Interrupts are enabled anyway)
  3407.         move.w    #1,$9c(a0)            ;clear intreq bit
  3408.         tst.b    sysx-buffptr(a1)        ;sysx??
  3409.         bne.s    sih_sysx
  3410.         move.w    bytesinbuff-buffptr(a1),d0    ;bytesinbuff
  3411.         beq.s    exsih                ;buffer empty
  3412.         movea.l    readbuffptr-buffptr(a1),a5    ;get buffer read pointer
  3413.         move.w    #$100,d1            ;Stop bit
  3414.         move.b    (a5)+,d1            ;get byte
  3415.         move.w    d1,$30(a0)            ;and push it to SERDAT
  3416.         cmpa.l    a1,a5                ;shall we reset ptr?
  3417.         bne.s    norrbuffptr            ;not yet..
  3418.         lea    -256(a1),a5
  3419. norrbuffptr    subq.w    #1,d0                ;one less bytes in buffer
  3420.         move.w    d0,bytesinbuff-buffptr(a1)    ;remember it
  3421.         move.l    a5,readbuffptr-buffptr(a1)    ;push new read ptr back
  3422. exsih        move.w    #$c000,$9a(a0)
  3423.         rts
  3424. sih_sysx    move.w    #$100,d1
  3425.         movea.l    sysxptr-buffptr(a1),a5    ;data pointer
  3426.         move.b    (a5)+,d1
  3427.         move.l    a5,sysxptr-buffptr(a1)
  3428.         move.w    d1,$30(a0)        ;-> SERDAT
  3429.         subq.l    #1,sysxleft-buffptr(a1)    ;sub data left length
  3430.         bne.s    exsih        ;not 0w
  3431.         lea    DB,a5
  3432.         clr.b    lastcmdbyte-DB(a5)
  3433.         bsr.s    StartNewDump
  3434.         bra.s    exsih
  3435.  
  3436. StartNewDump:    tst.w    dqentries-DB(a5)    ;queue empty?
  3437.         beq.s    snd_exit2
  3438.         movea.l    dqreadptr-DB(a5),a1    ;get read pointer
  3439.         move.w    (a1)+,d0        ;get message number (D0)
  3440.         cmpa.l    #dqwriteptr,a1        ;queue end?
  3441.         bne.s    snd_noresetbuff
  3442.         lea    dumpqueue-DB(a5),a1    ;reset write pointer
  3443. snd_noresetbuff    move.l    a1,dqreadptr-DB(a5)    ;and write it back.
  3444.         subq.w    #1,dqentries-DB(a5)
  3445. ; then attempt to search the given message (# in D0)
  3446.         move.l    _module-DB(a5),d1
  3447.         beq.s    StartNewDump
  3448.         move.l    d1,a1
  3449.         move.l    mmd_expdata(a1),d1
  3450.         beq.s    StartNewDump
  3451.         move.l    d1,a1
  3452.         move.l    52(a1),d1        ;exp_dump
  3453.         beq.s    StartNewDump
  3454.         move.l    d1,a1
  3455.         cmp.w    (a1),d0
  3456.         bge.s    StartNewDump
  3457.         addq.l    #8,a1            ;points to MMDDump ptr table
  3458.         add.w    d0,d0
  3459.         add.w    d0,d0            ;number *= 4
  3460.         adda.w    d0,a1
  3461.         movea.l    (a1),a1
  3462. ; initialize send variables (msg addr. in A0)
  3463. snd_found    move.l    (a1)+,sysxleft-DB(a5)    ;length
  3464.         move.l    (a1),sysxptr-DB(a5)    ;data pointer
  3465.         st    sysx-DB(a5)
  3466.         rts
  3467. snd_exit2    clr.b    sysx-DB(a5)        ;finish dump
  3468.         rts
  3469.  
  3470. _AddMIDIData    move.l    a6,-(sp)
  3471.         lea    DB,a6
  3472.         bsr.s    _AddMIDId
  3473.         move.l    (sp)+,a6
  3474.         rts
  3475.  
  3476. _AddMIDId    movem.l    a1-a3/a5,-(sp)
  3477.         tst.b    serportalloc-DB(a6)
  3478.         beq.s    retamd1
  3479.         movea.l    4.w,a5
  3480.         lea    $dff09a,a3
  3481.         move.w    #$4000,(a3)    ;Disable interrupts
  3482.         addq.b    #1,$126(a5)    ;ExecBase->IDNestCnt
  3483.         lea    buffptr-DB(a6),a2    ;end of buffer (ptr)
  3484.         move.w    -130(a3),d1    ;-130(a3) = $dff018 (SERDATR)
  3485.         btst    #13,d1
  3486.         beq.s    noTBEreq
  3487.         move.w    #$8001,2(a3)    ;request TBE [2(a3) = $dff09c]
  3488. noTBEreq    movea.l    (a2),a1        ;buffer pointer
  3489.         subq.w    #1,d0        ;-1 for DBF
  3490. adddataloop    move.b    (a0)+,d1    ;get byte
  3491.         bpl.s    norscheck    ;this isn't a status byte
  3492.         cmp.b    #$ef,d1        ;ignore system messages
  3493.         bhi.s    norscheck
  3494.         cmp.b    lastcmdbyte-DB(a6),d1    ;same as previous status byte?
  3495.         beq.s    samesb            ;yes, skip
  3496.         move.b    d1,lastcmdbyte-DB(a6)    ;no, don't skip but store.
  3497. norscheck    move.b    d1,(a1)+        ;push to midi send buffer
  3498.         addq.w    #1,8(a2)
  3499. samesb        cmpa.l    a2,a1            ;end of buffer??
  3500.         bne.s    noresbuffptr        ;no.
  3501.         lea    sendbuffer-DB(a6),a1    ;reset
  3502. noresbuffptr    dbf    d0,adddataloop
  3503.         move.l    a1,(a2)            ;push back new buffer ptr
  3504.         subq.b    #1,$126(a5)
  3505.         bge.s    retamd1
  3506.         move.w    #$c000,(a3)    ;enable interrupts again
  3507. retamd1        movem.l    (sp)+,a1-a3/a5
  3508.         rts
  3509.     ENDC
  3510.  
  3511.         DATA
  3512. DB:        ;Data base pointer
  3513.     IFNE    MIDI
  3514. sendbuffer    ds.b    256
  3515. buffptr        dc.l    sendbuffer
  3516. readbuffptr    dc.l    sendbuffer
  3517. bytesinbuff    dc.w    0
  3518. sysx        dc.b    0
  3519. lastcmdbyte    dc.b    0
  3520. sysxptr        dc.l    0
  3521. sysxleft    dc.l    0
  3522. dumpqueue    ds.w    16
  3523. dqwriteptr    dc.l    dumpqueue
  3524. dqreadptr    dc.l    dumpqueue
  3525. dqentries    dc.w    0
  3526.     ENDC
  3527. miscresbase    dc.l    0
  3528. timerdiv    dc.l    470000
  3529.     IFNE    AUDDEV
  3530. audiodevopen    dc.b    0
  3531. sigbitnum    dc.b    -1
  3532.     ENDC
  3533.     IFNE    MIDI
  3534. serportalloc    dc.b    0
  3535.     ENDC
  3536.         even
  3537.     IFNE    MIDI
  3538. preschgdata    dc.l    0
  3539. noteondata    dc.l    0
  3540.     ENDC
  3541. _module        dc.l    0
  3542. dmaonmsk    dc.w    0 ;\_May not be
  3543.     IFNE    MIDI
  3544. bytesinnotebuff    dc.w    0 ;/ separated!
  3545. noteonbuff    ds.b    (MAX_NUMTRACKS+2)*3
  3546.         even
  3547. intrson        dc.b    0,0
  3548. prevtbe        dc.l    0
  3549.     ENDC
  3550. intonmsk    dc.w    0
  3551.     IFNE    CIAB
  3552. _ciaresource    dc.l    0
  3553. craddr        dc.l    0
  3554.         dc.l    0    ;tloaddr
  3555.         dc.l    0    ;thiaddr
  3556.     ENDC
  3557. timerinterrupt    dc.w    0,0,0,0,0
  3558.         dc.l    timerintname,DB
  3559.         dc.l    _IntHandler
  3560.     IFNE    MIDI
  3561. serinterrupt    dc.w    0,0,0,0,0
  3562.         dc.l    serintname,buffptr,SerIntHandler
  3563.     ENDC
  3564.     IFNE    AUDDEV
  3565. allocport    dc.l    0,0    ;succ, pred
  3566.         dc.b    4,0    ;NT_MSGPORT
  3567.         dc.l    0    ;name
  3568.         dc.b    0,0    ;flags = PA_SIGNAL
  3569.         dc.l    0    ;task
  3570. reqlist        dc.l    0,0,0    ;list head, tail and tailpred
  3571.         dc.b    5,0
  3572. allocreq    dc.l    0,0
  3573.         dc.b    0,127    ;NT_UNKNOWN, use maximum priority (127)
  3574.         dc.l    0,allocport    ;name, replyport
  3575.         dc.w    68        ;length
  3576.         dc.l    0    ;io_Device
  3577.         dc.l    0    ;io_Unit
  3578.         dc.w    0    ;io_Command
  3579.         dc.b    0,0    ;io_Flags, io_Error
  3580.         dc.w    0    ;ioa_AllocKey
  3581.         dc.l    sttempo    ;ioa_Data
  3582.         dc.l    1    ;ioa_Length
  3583.         dc.w    0,0,0    ;ioa_Period, Volume, Cycles
  3584.         dc.w    0,0,0,0,0,0,0,0,0,0    ;ioa_WriteMsg
  3585. audiodevname    dc.b    'audio.device',0
  3586.     ENDC
  3587.     IFNE    CIAB
  3588. cianame        dc.b    'ciax.resource',0
  3589. _timeropen    dc.b    0
  3590.     ENDC
  3591. timerintname    dc.b    'OMEDTimerInterrupt',0
  3592.     IFNE    MIDI
  3593. serintname    dc.b    'OMEDSerialInterrupt',0
  3594. miscresname    dc.b    'misc.resource',0
  3595. serdev        dc.b    'serial.device',0
  3596. medname        dc.b    'OctaMED Pro modplayer',0
  3597.     ENDC
  3598.         even
  3599.     IFNE    MIDI
  3600. midiresd    dc.b    $e0,$00,$40,$b0,$01,$00
  3601.  
  3602. midicontrnum    ds.b    16
  3603.  
  3604. prevmidicpres    dc.l    0,0,0,0,0,0,0,0 ; 16 * 2 bytes
  3605.  
  3606. ; last MIDI RPN/NRPN (+1, zero = undefined)
  3607. prevmidipn    ds.w    16
  3608. ; last MIDI parameter type: RPN = 0, NRPN = 1
  3609. prevmidiptype    ds.b    16
  3610.  
  3611. prevmidipbend    dc.w    $2000,$2000,$2000,$2000,$2000,$2000,$2000,$2000
  3612.         dc.w    $2000,$2000,$2000,$2000,$2000,$2000,$2000,$2000
  3613.  
  3614. cmd3xsettings    ds.l    15    ;first word = ctrlr type, 2nd word = ctrlr num
  3615. sizeof_mcs    EQU    4    ;the size of an entry
  3616. mcs_type    EQU    0
  3617. mcs_controller    EQU    2
  3618.     ENDC
  3619. ; TRACK-data structures
  3620. t03d        ds.b    4*TRACKDATASZ
  3621. t463d        ds.b    (MAX_NUMTRACKS-4)*T415SZ
  3622. trackdataptrs    dc.l    t03d,t03d+TRACKDATASZ,t03d+2*TRACKDATASZ,t03d+3*TRACKDATASZ
  3623. ; Build pointer table. This works on Devpac assembler, other assemblers
  3624. ; may need modifications.
  3625. TRKCOUNT    SET    0
  3626.         REPT    (MAX_NUMTRACKS-4)
  3627.         dc.l    t463d+TRKCOUNT
  3628. TRKCOUNT    SET    TRKCOUNT+T415SZ
  3629.         ENDR
  3630.  
  3631. nextblock    dc.b    0 ;\ DON'T SEPARATE
  3632. nxtnoclrln    dc.b    0 ;/
  3633. numtracks    dc.w    0 ;\ DON'T SEPARATE
  3634. numlines    dc.w    0 ;/
  3635. numpages    dc.w    0
  3636. nextblockline    dc.w    0
  3637. rptline        dc.w    0 ;\ DON'T SEPARATE
  3638. rptcounter    dc.w    0 ;/
  3639. blkdelay    dc.w    0    ;block delay (PT PatternDelay)
  3640. bpmcounter    dc.w    0
  3641. bpmdiv        dc.l    3546895/2
  3642. fxplineblk    dc.l    0    ;for reading effects
  3643.     IFNE    FASTMEMPLAY
  3644.         XDEF    _fastmemplay,_fmp_buffsize
  3645. _use_fastmem    dc.w    0
  3646. _fmp_buffsize    dc.w    64    ;must be divisible by 4!
  3647. _fastmemplay    dc.w    1
  3648. ; Fastmemplay interrupt structures
  3649. fmpintname    dc.b    'OctaMED FastMemPlay Int',0
  3650.         even
  3651. fmpinterrupt0    dc.w    0,0,0,0,0
  3652.         dc.l    fmpintname,fmpstructs,_FmpIntHandler
  3653. fmpinterrupt1    dc.w    0,0,0,0,0
  3654.         dc.l    fmpintname,fmpstructs+fmp_sizeof,_FmpIntHandler
  3655. fmpinterrupt2    dc.w    0,0,0,0,0
  3656.         dc.l    fmpintname,fmpstructs+2*fmp_sizeof,_FmpIntHandler
  3657. fmpinterrupt3    dc.w    0,0,0,0,0
  3658.         dc.l    fmpintname,fmpstructs+3*fmp_sizeof,_FmpIntHandler
  3659.     ENDC
  3660.  
  3661. ; Fields in struct InstrExt (easier to access this way rather than
  3662. ; searching through the module).
  3663. holdvals    ds.b 63
  3664. decays        ds.b 63
  3665. finetunes    ds.b 63
  3666. flags        ds.b 63
  3667. ext_midipsets    ds.w 63
  3668. outputdevs    ds.b 63
  3669.         EVEN
  3670. rptrptlen    ds.l 126
  3671. playing_aura    ds.b 1
  3672.         EVEN
  3673.  
  3674. ; Below are the period tables. There's one table for each finetune position.
  3675.     IFNE    SYNTH|IFFMOCT
  3676.     dc.w    3424,3232,3048,2880,2712,2560,2416,2280,2152,2032,1920,1812
  3677.     dc.w    1712,1616,1524,1440,1356,1280,1208,1140,1076,1016,960,906
  3678.     ENDC
  3679. per0    dc.w    856,808,762,720,678,640,604,570,538,508,480,453
  3680.     dc.w    428,404,381,360,339,320,302,285,269,254,240,226
  3681.     dc.w    214,202,190,180,170,160,151,143,135,127,120,113
  3682.     dc.w    214,202,190,180,170,160,151,143,135,127,120,113
  3683.     dc.w    214,202,190,180,170,160,151,143,135,127,120,113
  3684.     dc.w    214,202,190,180,170,160,151,143,135,127,120,113
  3685.     IFNE    SYNTH|IFFMOCT
  3686.     dc.w    3400,3209,3029,2859,2699,2547,2404,2269,2142,2022,1908,1801
  3687.     dc.w    1700,1605,1515,1430,1349,1274,1202,1135,1071,1011,954,901
  3688.     ENDC
  3689. per1    dc.w    850,802,757,715,674,637,601,567,535,505,477,450
  3690.     dc.w    425,401,379,357,337,318,300,284,268,253,239,225
  3691.     dc.w    213,201,189,179,169,159,150,142,134,126,119,113
  3692.     dc.w    213,201,189,179,169,159,150,142,134,126,119,113
  3693.     dc.w    213,201,189,179,169,159,150,142,134,126,119,113
  3694.     dc.w    213,201,189,179,169,159,150,142,134,126,119,113
  3695.     IFNE    SYNTH|IFFMOCT
  3696.     dc.w    3376,3187,3008,2839,2680,2529,2387,2253,2127,2007,1895,1788
  3697.     dc.w    1688,1593,1504,1419,1340,1265,1194,1127,1063,1004,947,894
  3698.     ENDC
  3699. per2    dc.w    844,796,752,709,670,632,597,563,532,502,474,447
  3700.     dc.w    422,398,376,355,335,316,298,282,266,251,237,224
  3701.     dc.w    211,199,188,177,167,158,149,141,133,125,118,112
  3702.     dc.w    211,199,188,177,167,158,149,141,133,125,118,112
  3703.     dc.w    211,199,188,177,167,158,149,141,133,125,118,112
  3704.     dc.w    211,199,188,177,167,158,149,141,133,125,118,112
  3705.     IFNE    SYNTH|IFFMOCT
  3706.     dc.w    3352,3164,2986,2819,2660,2511,2370,2237,2112,1993,1881,1776
  3707.     dc.w    1676,1582,1493,1409,1330,1256,1185,1119,1056,997,941,888
  3708.     ENDC
  3709. per3    dc.w    838,791,746,704,665,628,592,559,528,498,470,444
  3710.     dc.w    419,395,373,352,332,314,296,280,264,249,235,222
  3711.     dc.w    209,198,187,176,166,157,148,140,132,125,118,111
  3712.     dc.w    209,198,187,176,166,157,148,140,132,125,118,111
  3713.     dc.w    209,198,187,176,166,157,148,140,132,125,118,111
  3714.     dc.w    209,198,187,176,166,157,148,140,132,125,118,111
  3715.     IFNE    SYNTH|IFFMOCT
  3716.     dc.w    3328,3141,2965,2799,2641,2493,2353,2221,2097,1979,1868,1763
  3717.     dc.w    1664,1571,1482,1399,1321,1247,1177,1111,1048,989,934,881
  3718.     ENDC
  3719. per4    dc.w    832,785,741,699,660,623,588,555,524,495,467,441
  3720.     dc.w    416,392,370,350,330,312,294,278,262,247,233,220
  3721.     dc.w    208,196,185,175,165,156,147,139,131,124,117,110
  3722.     dc.w    208,196,185,175,165,156,147,139,131,124,117,110
  3723.     dc.w    208,196,185,175,165,156,147,139,131,124,117,110
  3724.     dc.w    208,196,185,175,165,156,147,139,131,124,117,110
  3725.     IFNE    SYNTH|IFFMOCT
  3726.     dc.w    3304,3119,2944,2778,2622,2475,2336,2205,2081,1965,1854,1750
  3727.     dc.w    1652,1559,1472,1389,1311,1238,1168,1103,1041,982,927,875
  3728.     ENDC
  3729. per5    dc.w    826,779,736,694,655,619,584,551,520,491,463,437
  3730.     dc.w    413,390,368,347,328,309,292,276,260,245,232,219
  3731.     dc.w    206,195,184,174,164,155,146,138,130,123,116,109
  3732.     dc.w    206,195,184,174,164,155,146,138,130,123,116,109
  3733.     dc.w    206,195,184,174,164,155,146,138,130,123,116,109
  3734.     dc.w    206,195,184,174,164,155,146,138,130,123,116,109
  3735.     IFNE    SYNTH|IFFMOCT
  3736.     dc.w    3280,3096,2922,2758,2603,2457,2319,2189,2066,1950,1841,1738
  3737.     dc.w    1640,1548,1461,1379,1302,1229,1160,1095,1033,975,920,869
  3738.     ENDC
  3739. per6    dc.w    820,774,730,689,651,614,580,547,516,487,460,434
  3740.     dc.w    410,387,365,345,325,307,290,274,258,244,230,217
  3741.     dc.w    205,193,183,172,163,154,145,137,129,122,115,109
  3742.     dc.w    205,193,183,172,163,154,145,137,129,122,115,109
  3743.     dc.w    205,193,183,172,163,154,145,137,129,122,115,109
  3744.     dc.w    205,193,183,172,163,154,145,137,129,122,115,109
  3745.     IFNE    SYNTH|IFFMOCT
  3746.     dc.w    3256,3073,2901,2738,2584,2439,2302,2173,2051,1936,1827,1725
  3747.     dc.w    1628,1537,1450,1369,1292,1220,1151,1087,1026,968,914,862
  3748.     ENDC
  3749. per7    dc.w    814,768,725,684,646,610,575,543,513,484,457,431
  3750.     dc.w    407,384,363,342,323,305,288,272,256,242,228,216
  3751.     dc.w    204,192,181,171,161,152,144,136,128,121,114,108
  3752.     dc.w    204,192,181,171,161,152,144,136,128,121,114,108
  3753.     dc.w    204,192,181,171,161,152,144,136,128,121,114,108
  3754.     dc.w    204,192,181,171,161,152,144,136,128,121,114,108
  3755.     IFNE    SYNTH|IFFMOCT
  3756.     dc.w    3628,3424,3232,3051,2880,2718,2565,2421,2285,2157,2036,1922
  3757.     dc.w    1814,1712,1616,1525,1440,1359,1283,1211,1143,1079,1018,961
  3758.     ENDC
  3759. per_8    dc.w    907,856,808,762,720,678,640,604,570,538,508,480
  3760.     dc.w    453,428,404,381,360,339,320,302,285,269,254,240
  3761.     dc.w    226,214,202,190,180,170,160,151,143,135,127,120
  3762.     dc.w    226,214,202,190,180,170,160,151,143,135,127,120
  3763.     dc.w    226,214,202,190,180,170,160,151,143,135,127,120
  3764.     dc.w    226,214,202,190,180,170,160,151,143,135,127,120
  3765.     IFNE    SYNTH|IFFMOCT
  3766.     dc.w    3588,3387,3197,3017,2848,2688,2537,2395,2260,2133,2014,1901
  3767.     dc.w    1794,1693,1598,1509,1424,1344,1269,1197,1130,1067,1007,950
  3768.     ENDC
  3769. per_7    dc.w    900,850,802,757,715,675,636,601,567,535,505,477
  3770.     dc.w    450,425,401,379,357,337,318,300,284,268,253,238
  3771.     dc.w    225,212,200,189,179,169,159,150,142,134,126,119
  3772.     dc.w    225,212,200,189,179,169,159,150,142,134,126,119
  3773.     dc.w    225,212,200,189,179,169,159,150,142,134,126,119
  3774.     dc.w    225,212,200,189,179,169,159,150,142,134,126,119
  3775.     IFNE    SYNTH|IFFMOCT
  3776.     dc.w    3576,3375,3186,3007,2838,2679,2529,2387,2253,2126,2007,1894
  3777.     dc.w    1788,1688,1593,1504,1419,1339,1264,1193,1126,1063,1003,947
  3778.     ENDC
  3779. per_6    dc.w    894,844,796,752,709,670,632,597,563,532,502,474
  3780.     dc.w    447,422,398,376,355,335,316,298,282,266,251,237
  3781.     dc.w    223,211,199,188,177,167,158,149,141,133,125,118
  3782.     dc.w    223,211,199,188,177,167,158,149,141,133,125,118
  3783.     dc.w    223,211,199,188,177,167,158,149,141,133,125,118
  3784.     dc.w    223,211,199,188,177,167,158,149,141,133,125,118
  3785.     IFNE    SYNTH|IFFMOCT
  3786.     dc.w    3548,3349,3161,2984,2816,2658,2509,2368,2235,2110,1991,1879
  3787.     dc.w    1774,1674,1580,1492,1408,1329,1254,1184,1118,1055,996,940
  3788.     ENDC
  3789. per_5    dc.w    887,838,791,746,704,665,628,592,559,528,498,470
  3790.     dc.w    444,419,395,373,352,332,314,296,280,264,249,235
  3791.     dc.w    222,209,198,187,176,166,157,148,140,132,125,118
  3792.     dc.w    222,209,198,187,176,166,157,148,140,132,125,118
  3793.     dc.w    222,209,198,187,176,166,157,148,140,132,125,118
  3794.     dc.w    222,209,198,187,176,166,157,148,140,132,125,118
  3795.     IFNE    SYNTH|IFFMOCT
  3796.     dc.w    3524,3326,3140,2963,2797,2640,2492,2352,2220,2095,1978,1867
  3797.     dc.w    1762,1663,1570,1482,1399,1320,1246,1176,1110,1048,989,933
  3798.     ENDC
  3799. per_4    dc.w    881,832,785,741,699,660,623,588,555,524,494,467
  3800.     dc.w    441,416,392,370,350,330,312,294,278,262,247,233
  3801.     dc.w    220,208,196,185,175,165,156,147,139,131,123,117
  3802.     dc.w    220,208,196,185,175,165,156,147,139,131,123,117
  3803.     dc.w    220,208,196,185,175,165,156,147,139,131,123,117
  3804.     dc.w    220,208,196,185,175,165,156,147,139,131,123,117
  3805.     IFNE    SYNTH|IFFMOCT
  3806.     dc.w    3500,3304,3118,2943,2778,2622,2475,2336,2205,2081,1964,1854
  3807.     dc.w    1750,1652,1559,1472,1389,1311,1237,1168,1102,1041,982,927
  3808.     ENDC
  3809. per_3    dc.w    875,826,779,736,694,655,619,584,551,520,491,463
  3810.     dc.w    437,413,390,368,347,328,309,292,276,260,245,232
  3811.     dc.w    219,206,195,184,174,164,155,146,138,130,123,116
  3812.     dc.w    219,206,195,184,174,164,155,146,138,130,123,116
  3813.     dc.w    219,206,195,184,174,164,155,146,138,130,123,116
  3814.     dc.w    219,206,195,184,174,164,155,146,138,130,123,116
  3815.     IFNE    SYNTH|IFFMOCT
  3816.     dc.w    3472,3277,3093,2920,2756,2601,2455,2317,2187,2064,1949,1839
  3817.     dc.w    1736,1639,1547,1460,1378,1301,1228,1159,1094,1032,974,920
  3818.     ENDC
  3819. per_2    dc.w    868,820,774,730,689,651,614,580,547,516,487,460
  3820.     dc.w    434,410,387,365,345,325,307,290,274,258,244,230
  3821.     dc.w    217,205,193,183,172,163,154,145,137,129,122,115
  3822.     dc.w    217,205,193,183,172,163,154,145,137,129,122,115
  3823.     dc.w    217,205,193,183,172,163,154,145,137,129,122,115
  3824.     dc.w    217,205,193,183,172,163,154,145,137,129,122,115
  3825.     IFNE    SYNTH|IFFMOCT
  3826.     dc.w    3448,3254,3072,2899,2737,2583,2438,2301,2172,2050,1935,1827
  3827.     dc.w    1724,1627,1536,1450,1368,1292,1219,1151,1086,1025,968,913
  3828.     ENDC
  3829. per_1    dc.w    862,814,768,725,684,646,610,575,543,513,484,457
  3830.     dc.w    431,407,384,363,342,323,305,288,272,256,242,228
  3831.     dc.w    216,203,192,181,171,161,152,144,136,128,121,114
  3832.     dc.w    216,203,192,181,171,161,152,144,136,128,121,114
  3833.     dc.w    216,203,192,181,171,161,152,144,136,128,121,114
  3834.     dc.w    216,203,192,181,171,161,152,144,136,128,121,114
  3835.  
  3836. _periodtable
  3837.     dc.l    per_8,per_7,per_6,per_5,per_4,per_3,per_2,per_1,per0
  3838.     dc.l    per1,per2,per3,per4,per5,per6,per7
  3839.  
  3840.     IFND    __G2
  3841.         section "datachip",data,chip ;for A68k
  3842.     ENDC
  3843.     IFD    __G2
  3844.         section "datachip",data_c ;this is for Devpac 2
  3845.     ENDC
  3846.         XDEF    _modnum
  3847. _chipzero    dc.l    0
  3848. _modnum        dc.w    0    ;number of module to play
  3849.  
  3850.     IFNE    FASTMEMPLAY
  3851.         BSS
  3852. fmpstructs    ds.b    fmp_sizeof*4
  3853.         SECTION    "ChipMemBuff",bss_c
  3854. _audiobuff    ds.w    3200
  3855.     ENDC
  3856.  
  3857.         END
  3858.